Limits and allowances
Every number on this page is a mechanism, cited to the thing that enforces it. Prices are on the pricing page.
Request limits
Section titled “Request limits”Enforced on every ingest request, on every deployment, regardless of plan.
| Limit | Value | Enforced by | Response when exceeded |
|---|---|---|---|
| Rows per request | 5,000 | POST /v1/ingest | 400 |
| GenAI spans per request | 5,000 | POST /v1/traces | 413 |
| Request body | 8 MiB | Both ingest endpoints | 413 |
| Retained content per field | 100 KiB | The ingest worker | Silently truncated, with content_truncated set |
The body limit is checked twice: once against the bytes on the wire, and again after gzip decompression. A small compressed body that expands past 8 MiB is rejected, so a compression bomb cannot get past the first check.
The SDKs stay well inside these. They cap a batch at 4 MiB, split anything larger
in half and retry each side down to a single row, and handle a 413 the same
way. If you write your own client, do the same. See
Write your own client.
The monthly call allowance
Section titled “The monthly call allowance”A workspace has a monthly captured-call allowance, counted per calendar month in UTC.
| Plan | Allowance |
|---|---|
free | 100,000 captured calls per month |
managed | No allowance. The counter still runs, and nothing gates on it |
These are the only two values the database permits. There is no third tier.
How the count works
Section titled “How the count works”Rows are counted as the worker processes them, into a per-workspace, per-month counter. The check happens at accept time, before the batch is written: if the counter has already reached the allowance, the request is refused.
Because the check is “already at or above the allowance” rather than “would exceed it”, a batch that crosses the line is accepted in full and the next request is refused. You will see slightly more than 100,000 calls in the month that ran out.
What happens when it is spent
Section titled “What happens when it is spent”POST /v1/ingest and POST /v1/traces return 402 with a structured body:
{ "detail": { "code": "quota_exceeded", "message": "This workspace has reached its monthly captured-call limit.", "quota": { "period_month": "2026-09-01", "calls_counted": 100000, "allowance": 100000, "over_quota": true, "percent_used": 100.0 } }}The dashboard shows a Capture paused banner and the sidebar meter turns red. Everything already captured stays queryable. Capture resumes at the start of the next UTC month, or when the allowance is raised.
The SDKs do not special-case 402. They treat it as a non-202 response, back
off, and keep dropping rows. A process that runs past the allowance is not
harmed, but it is not buffering for you either.
The sidebar meter warns at 80 percent and offers Book a call, which opens an upgrade request rather than charging anything.
Retention
Section titled “Retention”| Setting | Default | Range |
|---|---|---|
| Metadata retention | 90 days | 1 to 3,650 days, set per workspace |
A background job runs hourly, deleting calls older than the workspace’s retention in batches of 10,000, then removing the batch ledger entries that no longer have any calls pointing at them. The per-run batch is clamped to between 1 and 50,000 rows, so a large backlog drains over several runs rather than in one statement.
Two details that are easy to get wrong:
- On a managed deployment the deletion job only touches
freeworkspaces. Amanagedworkspace keeps its rows beyond the 90 day setting unless the operator removes them another way. - On a BYOC deployment the job applies to every workspace, using the same per-workspace retention value.
Retention is why the Traces window tops out at 90 days: a longer window would show a hole rather than history.
Content
Section titled “Content”| Stage | Cap | Configurable |
|---|---|---|
| Leaves your process | 1 MiB per field | Yes, METERGRAPH_TEXT_MAX_BYTES. Floor of 1, no ceiling |
| Retained after ingest | 100 KiB per field | No |
The request, the response and the serialized tool-call list are each bounded independently at both stages. See Captured fields.
Tokens and sessions
Section titled “Tokens and sessions”| Limit | Value |
|---|---|
| Ingest key format | mg_ plus 48 hex characters |
| Ingest session token TTL | 1 hour |
| Session refresh margin | The SDK re-exchanges within 30 seconds of expiry |
| Scopes a dashboard key can carry | ingest, and only ingest |
Capability by deployment profile
Section titled “Capability by deployment profile”The real gating in Metergraph is by deployment profile, not by plan. A plan tier is a label and an allowance. What a deployment can do is decided by which profile it runs under.
There are three profiles: managed (the hosted cloud, and the customer-local
Docker stack), byoc-core (a deployment in your own AWS account), and local,
which shares the managed capability set.
| Capability | managed and local | byoc-core |
|---|---|---|
| Telemetry ingest and dashboard | Yes | Yes |
| Alerts | Yes | Yes |
| API keys | Yes | Yes |
| Membership | Yes | Yes |
| Workspace settings | Read and write | Read only |
| Reports | Yes | Yes |
| Analysis runs | Yes | Yes |
| Optimization recommendations | Yes | Yes |
| Evaluations and scorecards | Yes | — |
| Datasets | Yes | — |
| Replay simulations | Yes | — |
| Canaries | Yes | — |
| Billing and upgrade requests | Yes | — |
| External delivery, including pull requests | Yes | — |
| Self-service signup and invitations | Yes | — |
| Platform administration | Yes | — |
| Batch API provider probes | Yes | — |
| MCP agent API | Yes | — |
| Import sync from another vendor | Yes | — |
Gating is fail-closed at the HTTP layer: a request to a route whose capability is not available on this profile is refused before it reaches a handler. Core ingest, traces, performance, alerts, API keys, identity and membership reads carry no capability requirement and are always available.
Background work is gated too. On byoc-core, the worker runs only ingest batch
processing and detector scans.
You can read the live answer for any deployment:
curl -sS https://app.metergraph.dev/v1/deployment{ "deployment_profile": "managed", "cloud": "aws", "capabilities": ["agent_api", "alerts", "..."] }That endpoint needs no authentication and is cacheable for five minutes.
Within a workspace, three roles.
| Role | Can |
|---|---|
owner | Everything, including renaming the workspace, inviting people, and approving external actions |
member | Everything operational: create and disable ingest keys, acknowledge alerts, start an analysis |
viewer | Read only. Cannot acknowledge an alert, manage keys, or change replay configuration |
What is not a limit
Section titled “What is not a limit”Some things the old documentation described as tier-gated are not gated at all.
| Claim you may have seen | Reality |
|---|---|
| Free, Growth and Scale tiers | The database permits exactly free and managed. There is no Growth or Scale |
| Per-plan feature entitlements | The entitlement check returns true for every feature on every plan. It is a compatibility shim, not a gate |
| Content capture as a paid feature | Content capture is on by default and controlled entirely client-side, by METERGRAPH_CAPTURE_TEXT and per-scope capture_text |
| Canaries and rollout as a shipping capability | The canaries capability exists on the managed profile, but there is no write path that puts a challenger model into the config document. model_for() returns your default |
Related
Section titled “Related”- Ingest API for the status codes above
- Errors for what to do about each one
- Choosing a deployment
- Captured fields