Signals · 3 min read · Updated 2026-08-14
Sampling you can explain
Keep every failing transaction. Sample a tenth of the rest. Bill the root, not every query. That is the whole policy.
Unsampled APM on a busy site is a denial-of-service against your own invoice. Auto-instrumented PDO and fetch can multiply one request into dozens of spans. The metering question is not “how do we count everything?” It is “what is worth counting, and what must never be dropped?”
The problem
Two failure modes show up in every APM rollout. Sample too little and you miss the slow-but-successful checkout. Sample too much — or bill every child span — and the finance meeting becomes a tracing meeting. Tail-based sampling (decide after you have seen the whole trace) needs a collector in the path. Head-based sampling (decide at the start) can run in the SDK.
What it is
Talaria uses head-based sampling in official SDKs. When a transaction starts, the SDK decides whether the trace is in. If it is in, children are recorded. If it is out, the SDK does not send the tree. Dropped spans are not stored and not billed.
- Tracing is off until
enableTracingis true ortracesSampleRate > 0. - Once on, transactions that error — span status
error, or an error captured in-scope — are sampled at 100%. - Successful transactions default to
tracesSampleRate0.10 (10%). - The billable unit is one accepted sampled root span. Children are included.
What it gives a team
- A sentence you can say to a stakeholder: we keep failing requests, we sample a tenth of the rest, we do not charge per SQL statement.
- Predictable volume. A chatty ORM cannot turn one page view into a hundred billable units.
- Debuggability where it matters. The trace attached to an issue is not missing because of a dice roll.
How Talaria does it
SDKs enforce the sample decision. Ingest still validates IDs, caps 200 children per transaction, sanitizes SQL literals and URLs, and meters roots via EntitlementService.assertCanAcceptTransaction. Rejected ingest (401 / 422 / 429) is not billed. Request bodies are not captured by default.
OTLP/HTTP JSON at /otlp/v1/traces is an advanced Collector path for teams already on OpenTelemetry. Native SDKs remain the supported way to get head sampling and error-boosted retention.
How to read it
If Performance looks sparse, tracing may still be off. If error traces appear but successful ones barely do, you are seeing the 10% default working as designed — raise tracesSampleRate only after you have watched a week of transaction counts against your plan quota.
RED duration is computed from sampled roots. Error rate is not under-sampled the same way, because failures are kept. Do not compare a 10%-sampled p95 to a 100% error count as if they were the same census.
Turn it on
await Talaria.init(TalariaOptions(
dsn: 'https://api.newtalaria.com',
apiKey: const String.fromEnvironment('TALARIA_API_KEY'),
environment: 'production',
enableTracing: true,
tracesSampleRate: 0.1, // 10% of successful transactions; errors always traced
));What this is not
Talaria does not do tail-based sampling, central sample decisions across a mesh, or a “spans maze” as a public meter. A Collector can sit in front of OTLP ingest for teams that already have one; we do not sell that collector, and we do not require it.
Related guides
Signals · 3 min
Transactions, traces, and spansA trace is one request’s path. A span is a timed unit of work. A transaction is the root span Talaria meters.
Signals · 3 min
What SDK-native APM actually isApplication performance from inside your process — transactions, RED, and release health — without a host agent or an observability maze.
Signals · 3 min
RED metrics: rate, errors, durationThree numbers that describe a service from the outside: how often it is called, how often it fails, and how long it takes.