Head vs tail sampling in OpenTelemetry — when does each break?
632 views
29 of 106
1
The problem
Question presented to candidate:
"We cannot afford to store every trace. Explain head sampling and tail sampling in OpenTelemetry, when you would use each, and the specific ways each one fails in production."
What a strong answer should cover:
Head sampling: decided when the root span starts, usually from the trace ID (TraceIdRatioBased) and propagated through the sampled flag with a parent-based sampler; cheap and stateless, but blind to errors and latency that have not happened yet
Head failure modes: rare errors and slow requests mostly dropped, inconsistent decisions if services sample independently (broken traces), counts that need scaling by 1/rate
Tail sampling: the Collector buffers all spans of a trace for a decision wait, then applies policies (errors, latency, attributes, probabilistic, rate limits)
Tail failure modes: needs all spans of a trace on one Collector (trace-ID routing), spans arriving after the wait, memory proportional to spans/s times the wait, shipping 100% of spans, reshuffles when the tier scales
The usual hybrid: compute request metrics before sampling, light head sampling (or none) in the SDK, tail sampling in a routed gateway tier
Code / implementation expected: Optional — the example compares both on 100,000 simulated traces and shows each failure mode with numbers.
opentelemetry
sampling
otel-collector
2
Try it yourself
Sketch your approach before you read the solution. That is what the interview tests.
Stuck? Get a hint.
A short nudge toward the approach. It will not give the answer away.
3
Solution
Target Audience: Engineers who have set up tracing and now have to choose a sampling strategy, and candidates who want to discuss sampling trade-offs with numbers rather than slogans.
Difficulty: Medium
Verified with: Node 22.22 and Python 3.12 (both print identical output). Tail sampling processor settings (decision_wait default 30 s described as time since the first span, num_traces default 50000) from the Grafana Alloy reference for otelcol.processor.tail_sampling (a wrapper of the upstream processor) and a third-party guide; the SDK default sampler from the OpenTelemetry .NET documentation; check the README of the Collector version you run, since defaults can change.
How to read this doc: Every idea is explained in plain language first, then tagged with 📌 Interview term: so you also learn the words an interviewer expects. Every number comes from running th
The solution is hidden so you can try first
15 min read · 11 sections
4
Read the code
Head vs tail sampling on 100,000 traces: what each keeps, inconsistent per-service sampling, unrouted spans and decision_wait