Trace sampling, quotas and node capacity
Monthly quotas, rate limits, retention and the node disk budget; how to sample by trace without breaking traces that cross services.
On this page
Traces and logs grow with traffic, not with problems. This page shows the limits on the default plan, what happens when you reach them, and how to send less without losing the traces you need.
Limits on the default plan#
| Limit | Default | What happens at the limit |
|---|---|---|
| Traces per month, for the workspace | 5 GB | Further trace requests get 429 until the month resets |
| Logs per month, for the workspace | 5 GB | Further log requests get 429 until the month resets |
| Sending rate, per project and signal | 1 MiB/s, bursts to 8 MiB | 429 with Retry-After; exporters wait and retry |
| Retention | 7 days (adjustable up to 90) | Older data is deleted on your node |
| Time traces and logs may wait at the edge while your node is offline | 15 minutes | Older waiting data is dropped and counted as Expired in the buffer; a full buffer answers 503 |
Your plan may differ; Project settings → Traces, logs and metrics received shows the quota used, retention, what was accepted and what was dropped, by reason. Errors are not part of these numbers and wait at the edge much longer while a node is offline.
Your node's disk#
Traces and logs share at most 30 % of your node's disk, split between them (half each by default; owners and admins can change the split in the same card). When a signal outgrows its share, its oldest days are deleted early and the card shows how many days are really kept. When the node is under heavy load — 85 % of memory or disk — it stops taking traces and logs first; errors keep flowing.
Sample traces, not requests at random#
Head sampling decides at the start of a trace whether to keep it. Use the parent-based ratio sampler, so a service follows the decision of the service that called it and traces never arrive half-kept:
export OTEL_TRACES_SAMPLER=parentbased_traceidratioexport OTEL_TRACES_SAMPLER_ARG=0.10.1 keeps one trace in ten. Set the same sampler in every service; only the first service's ratio decides, the others follow it. Errors are not affected — they are sent by your error SDK, not sampled by OpenTelemetry.
Logs are not sampled by the trace sampler: a log line written during an unsampled request is still sent, with its trace id, but that trace has no spans. To send fewer logs, raise your logger's level (for example to warn in production).
Send less of what you do not read#
Turn off noisy instrumentations (file system, DNS, every Redis call) — each recipe shows the variable.
Drop health checks and readiness probes; in the Collector a
filterprocessor can do it for all services at once.Compress:
OTEL_EXPORTER_OTLP_COMPRESSION=gzip. Quotas and the rate limit count bytes as received, so the same data uses less of both.Send metrics only where you read them (
OTEL_METRICS_EXPORTER=otlpper service), once a minute. Their cost is the number of series, not the number of requests — keep unbounded values such as user ids off metric attributes (limits).
Spotted something wrong or missing? Tell us: hello@belvador.dev