Skip to content

Metrics and cost ​

Both are instruments, not numbers we ask you to take on faith.

In-process counters ​

bash
# per-route latency percentiles over this process's recent requests
curl -H "Authorization: Bearer $SODAMEM_API_KEY" localhost:8000/v1/metrics

# cumulative LLM token spend, split by ingest vs answer
curl -H "Authorization: Bearer $SODAMEM_API_KEY" localhost:8000/v1/usage

Both are in-process and reset on restart. They are counters for "what is this deployment doing right now", not a billing record.

/v1/metrics returns a routes map of {count, min, …, max} per route. /v1/usage returns by_operation and a total.

Prometheus ​

For anything that has to outlive a restart, scrape instead:

bash
curl -H "Authorization: Bearer $SODAMEM_API_KEY" localhost:8000/metrics

It exposes request counts (a true monotonic counter, not the latency ring), duration quantiles in seconds, and cumulative LLM tokens per operation. It sits behind the same API key as everything else, so a scrape config needs a bearer_token:

yaml
scrape_configs:
  - job_name: sodamem
    authorization:
      type: Bearer
      credentials: <SODAMEM_API_KEY>
    static_configs:
      - targets: ['sodamem:8000']

Routes with no traffic are absent rather than reported as zero, because a zero reads as "this is instantaneous" or "this is free".

Why there is no OpenTelemetry exporter ​

OTel earns its cost on distributed tracing. This is one process. Scraping covers the actual need at zero added dependencies.

Why we publish no headline latency number ​

It depends on hardware, store size, embedder and concurrency to a degree that makes a single figure close to meaningless. Measure it on your own deployment with /v1/metrics.

Reading cost ​

/v1/usage splits ingest from answer deliberately:

  • ingest is output-token heavy — extraction writes facts
  • answer is input-heavy — the planner reads retrieved evidence

A single total hides the only comparison worth making. And the cheap retrieval tier contributes nothing to either number, because it makes no model call at all — see Retrieval tiers.

Maintenance costs tokens too ​

Entity profiles are rebuilt on demand, never on a timer — SodaMem ships no scheduler, because when to spend those tokens is a deployment decision:

bash
curl -X POST localhost:8000/v1/maintenance/dream \
  -H "Authorization: Bearer $SODAMEM_API_KEY" -H "Content-Type: application/json" \
  -d '{"user_id":"u1","async_mode":true}'

Idempotent, resumable, and safe to overlap: a second call while one is running returns status:"already_running" and does nothing. The response carries remaining_stale, so a cron entry that just runs every hour converges without anyone having to pick a batch size.

Apache-2.0 licensed.