Dynamic (Adaptive) Sampling in OpenTelemetry

Dynamic (Adaptive) Sampling in OpenTelemetry

A deep, plain-English guide to how a tracing pipeline can change its own sampling rates on the fly, keeping the traces that matter, dropping the noise, and staying inside a budget while traffic rises and falls.

Imagine you run a huge library that receives a million visitors every day. You want to know what visitors do inside, so you decide to follow them with a notebook. Following every visitor is impossible, so you follow some. If you follow one visitor in every hundred, you save a lot of effort, but on a quiet Sunday you may follow only three people and learn almost nothing. Worse, the one visitor who got lost, got angry, and knocked over a shelf may never be one of the people you followed. What you really want is a smart assistant who watches the crowd, follows more people when it is quiet, follows fewer when it is packed, and always follows anyone who looks lost or upset. That assistant is the idea behind dynamic, or adaptive, sampling.

This guide explains that idea in the world of OpenTelemetry, the open standard for collecting traces, metrics, and logs from software. We start from the very beginning, build up the vocabulary, look at what OpenTelemetry actually provides today, and then go deep into how adaptive sampling is designed, deployed, secured, measured, and kept honest. No prior knowledge is assumed.

1Why Sampling Exists at All

Before we adapt anything, we need to understand the problem that sampling solves: too much telemetry, too little budget.

The firehose problem

A modern application is rarely one program. It is often dozens or hundreds of small services that call each other. One click on a shopping site may touch a web gateway, a login service, a cart service, a pricing service, a stock service, a payment service, and several databases. Each step can produce a record describing what happened. When thousands of users click at the same time, the number of records becomes enormous.

A trace is the story of one request as it travels through all of those services. A span is one chapter of that story, for example “the cart service talked to its database for 12 milliseconds”. A single trace may hold five spans or five hundred. A busy system can produce hundreds of thousands of spans every second.

Simple Analogy

Think of a security camera in a shopping mall. Recording every camera at full quality, forever, would fill up every hard disk you own. So malls keep recent footage, compress old footage, and save special clips when something happens. Telemetry has the same problem and needs the same kind of thinking.

Three kinds of cost

Keeping every trace is expensive in three separate ways, and it helps to name them because different sampling strategies fight different costs.

Cost 1

Network and CPU

Creating spans, packing them, and sending them across the network uses processor time and bandwidth inside your running applications.

Cost 2

Pipeline and storage

Collectors, queues, and databases must handle every span you send. Storage grows fast and queries get slower as it grows.

Cost 3

Vendor and human bill

Most hosted observability products charge by volume. Engineers also lose time searching through piles of boring, identical traces.

Most traces are boring

Here is the key insight that makes sampling worthwhile. In a healthy system, about 99 out of every 100 requests look almost the same: fast, successful, and uninteresting. The valuable traces are the slow ones, the failed ones, and the unusual ones. If you could keep all the valuable traces and only a small taste of the boring ones, you would lose very little knowledge and save a huge amount of money.

i
Remember

Sampling is not about losing data carelessly. It is about deciding, on purpose, which data is worth keeping so that the data you keep still answers your questions.

Why a fixed rule is not enough

The simplest sampling rule is “keep 1 percent”. It is easy, but traffic is never steady. At 3 a.m. a service may handle 50 requests a minute, and 1 percent means you keep a trace every two minutes, which is too thin to see anything. During a sale the same service may handle 500,000 requests a minute, and 1 percent still floods you with 5,000 traces a minute. A rule that is right at one moment is wrong at another. Adaptive sampling exists because the world moves and the rule must move with it.

2OpenTelemetry Foundations You Need First

A short, friendly refresher on the pieces of OpenTelemetry that sampling touches.

What OpenTelemetry is

OpenTelemetry, often shortened to OTel, is an open standard and a set of tools for producing and moving telemetry. It is vendor neutral, which means you can create your data once and send it to many different backends. It is maintained in the open under the Cloud Native Computing Foundation, and it is one of the most active projects in that foundation.

The building blocks

Piece 1

API

The small set of calls that application and library code uses to create spans. It does nothing heavy on its own, which keeps libraries lightweight.

Piece 2

SDK

The engine that sits inside your application, implements the API, and decides what to do with spans, including whether to record them at all.

Piece 3

Exporter

The part of the SDK that sends finished spans out, usually with the OpenTelemetry Protocol, called OTLP.

Piece 4

Collector

A separate program that receives telemetry, processes it, and forwards it. It is built from receivers, processors, exporters, connectors, and extensions.

Piece 5

Sampler

A small decision-maker inside the SDK. When a span is about to start, it answers one question: should this trace be recorded and kept?

Piece 6

Context propagation

The way trace identity travels between services, usually in request headers, so every service knows which trace it belongs to.

Traces, metrics, and logs side by side

OpenTelemetry handles three kinds of telemetry, and sampling affects them very differently. Metrics are numbers measured over time, such as requests per second. They are small, they can be combined cheaply, and most teams keep them complete. Logs are lines of text describing events. They can be large, and teams often filter them by severity. Traces are the detailed stories of individual requests. They are the largest and the most expensive per request, which is why sampling is mostly discussed in the context of traces.

The three kinds can be linked together. A log line can carry the trace identifier of the request that produced it, and a metric can point to an example trace. This linking is the reason sampling needs care: if a log points to a trace that the sampler dropped, the link leads nowhere. A good design keeps the linked traces for the events that matter most.

Trace identity and the sampled flag

Every trace has a unique trace identifier. When service A calls service B, it passes that identifier along, together with the identifier of the calling span and a small set of flags. One of those flags says whether the trace is being sampled. This follows the W3C Trace Context standard. There is also an optional extra field called trace state, where vendors and the OpenTelemetry sampling specification can pass small notes along the chain.

Simple Analogy

Trace context is like a wristband handed out at a theme park entrance. It carries a ticket number so every ride knows who you are. The sampled flag is a coloured sticker on the wristband that tells every ride attendant, “Yes, take notes about this guest.”

The Collector pipeline in one picture

The Collector is where much of the more advanced sampling lives, so it is worth seeing its shape. Data enters through receivers, passes through a chain of processors, and leaves through exporters. Sampling processors sit in the middle of that chain.

flowchart LR
  A["Applications with OTel SDK"] --> B["Receiver (OTLP)"]
  B --> C["Processors (batch, filter, sampling)"]
  C --> D["Exporter (OTLP)"]
  D --> E["Tracing backend"]
        
FIG 1 — The basic Collector pipeline where sampling processors live
!
Common Misconception

People often think “sampling” means “turning tracing off for some users”. It does not. Sampling decides per trace, and a good sampling design keeps the whole trace together or drops the whole trace together.

3Sampling Basics: Head and Tail

Every adaptive design is built on top of two older ideas. You must understand both to see why adaptation is hard.

Head sampling: decide at the start

In head sampling, the decision is made at the very beginning of the trace, when the first span, called the root span, is created. The sampler looks only at the information available at that moment, such as the trace identifier, the name of the operation, and a few starting attributes. Once it says yes or no, that decision is written into the trace context and followed by every other service.

The big advantage is cost. If the answer is no, the application barely does any work for that trace: no spans are recorded, nothing is sent, nothing is stored. The big weakness is blindness. At the start of a request, nobody knows whether it will become slow or fail. A head sampler cannot say “keep the slow ones” because slowness has not happened yet.

Tail sampling: decide at the end

In tail sampling, every span is recorded and sent to a Collector. The Collector gathers the spans of each trace, waits until the trace looks complete, and then decides. Now it can look at the whole story: how long it took, whether any span had an error, how many spans there were, and which services were involved. It can say “keep all errors, keep everything slower than two seconds, keep a small taste of the rest”.

The strength is smart choice. The weakness is cost and complexity. All spans must travel to the Collector before any are dropped. The Collector must hold spans in memory while it waits. And every span of a trace must arrive at the same Collector instance, or the decision will be made on an incomplete picture.

QuestionHead SamplingTail Sampling
When is the decision made?At the start of the traceAfter the trace is collected
Where does it run?Inside the SDK in each serviceIn a Collector or gateway
Can it keep errors and slow traces?No, it cannot know yetYes, it sees the full outcome
Savings on application overheadHigh, dropped traces are never recordedLow, everything is recorded and sent first
Memory neededAlmost noneSignificant, spans are buffered
Operational complexityLowHigh, needs routing and scaling care
Simple Analogy

Head sampling is a bouncer at the door who lets in one person out of every ten without knowing anything about them. Tail sampling is a film editor who watches all the footage after the day is over and keeps only the interesting scenes. The bouncer is cheap but blind. The editor is smart but needs a big editing room.

The simple arithmetic of probability sampling

Probability sampling is easy to picture. Choose a number between zero and one, called the sampling probability. A probability of 0.1 means “keep about one trace in ten”. The sampler turns each trace identifier into a number, compares it with the probability, and keeps the trace if the number falls under the line. Because the trace identifier is effectively random, about the right share of traces passes the test, and because the identifier never changes, the same trace always gets the same answer wherever it is evaluated.

This is why the trace identifier matters so much. If every service derives its decision from the same identifier, they all agree without needing to talk to each other. The decision becomes a pure calculation, which is fast, cheap, and repeatable. It also means you can predict your costs: if you receive a million traces an hour and keep one percent, you will store about ten thousand.

The weakness of a fixed probability is exactly what we said earlier. It follows traffic. The number you pick on a quiet Tuesday is wrong on a busy Friday, and nobody wants to edit it by hand every hour.

Fixed versus dynamic

Both head and tail sampling can be fixed or dynamic. A fixed head sampler might always keep 10 percent. A fixed tail sampler might always keep errors plus 5 percent of everything else. A dynamic version of either one changes its numbers over time based on what it observes. That second word, dynamic, is the subject of the rest of this guide.

4What “Dynamic” and “Adaptive” Really Mean

The words are used loosely across the industry, so let us pin them down.

A working definition

Dynamic sampling, also called adaptive sampling, is any sampling approach in which the keep-or-drop probability is not a single constant but is continuously recalculated from live observations of the traffic. The system watches how many traces are flowing, what they look like, and how much data it is allowed to keep, and then it adjusts the sampling rate to hit a goal.

“A fixed sampler follows a rule. An adaptive sampler follows a goal.”

The goals an adaptive sampler can chase

Goal A

Throughput target

Keep roughly a chosen number of traces per second, no matter how much traffic arrives. Busy periods get a lower percentage and quiet periods get a higher one.

Goal B

Fairness across groups

Make sure rare operations, small customers, or unusual endpoints still get enough traces, instead of being drowned by the loudest group.

Goal C

Interesting first

Raise the rate for traces that look important, such as errors and slow requests, and lower it for traces that look routine.

Goal D

Budget control

Stay under a fixed daily volume or cost ceiling by turning rates down automatically as the budget is consumed.

The three ingredients of every adaptive sampler

No matter which product or design you meet, adaptive sampling always has three parts working together.

1

Observe

Measure the live traffic: how many traces per second, per group, per outcome. This is the sensing part.

2

Decide

Compare what you see with the goal and calculate a new sampling probability for each group. This is the thinking part.

3

Apply and record

Use the new probability for future decisions and write the probability next to each kept trace so counts can be corrected later. This is the acting and remembering part.

How adaptive sampling differs from nearby ideas

Several neighbouring techniques are often confused with adaptive sampling. Separating them makes later chapters easier to follow.

IdeaWhat it doesHow it differs from adaptive sampling
Rate limitingDrops anything above a fixed number per secondIt is a hard cap with no fairness and no memory of which keys deserve more, so bursts crowd out rare traces
FilteringRemoves traces that match a rule, such as health checksIt is a fixed rule about content, not a controller that reacts to volume
Dynamic configurationLets people change settings without a restartIt is the delivery channel for new numbers, while adaptive sampling is the logic that chooses the numbers
Priority samplingKeeps traces that score highest on importanceIt ranks traces but may not manage the total budget unless combined with a rate controller
Adaptive samplingContinuously retunes probabilities to meet a goalIt senses the world, decides, acts, and records what it did

In real systems you will usually combine several of these. A health-check filter removes pure noise, a priority rule protects errors, a rate cap guards against disasters, and an adaptive controller handles everything in between.

Simple Analogy

A thermostat in your home is an adaptive controller. It measures the room, compares it with your target temperature, and turns the heater up or down. It does not follow a fixed schedule of “heater on for ten minutes”. An adaptive sampler is a thermostat for telemetry volume.

!
Important Honesty Note

OpenTelemetry does not ship one single feature named “adaptive sampling” that you switch on. It gives you building blocks: samplers, trace state fields for probability, a tail sampling processor, a probabilistic sampler processor, and extension points for remote configuration. Adaptive behaviour is something you assemble from those blocks or get from a backend or product built on them.

5What OpenTelemetry Actually Provides

A tour of the real building blocks, from SDK samplers to Collector processors to remote control channels.

SDK samplers

Every OpenTelemetry SDK includes a small family of built-in samplers. They are the head sampling tools. Two are trivial: one that always keeps and one that never keeps. A third keeps a fixed fraction of traces by looking at the trace identifier, so the same trace identifier always produces the same answer. A fourth, called the parent-based sampler, is a wrapper that says “if my parent already decided, follow my parent; otherwise ask this other sampler”. Parent-based behaviour is what keeps traces whole across services, so almost every production setup uses it.

Probability samplers and the trace state

A subtle problem appears when you sample in more than one place. If service A keeps 50 percent and service B keeps 50 percent independently, you do not get 50 percent of whole traces. You get a messy mix of broken ones. To fix this, the OpenTelemetry sampling specification describes consistent probability sampling. Each trace carries a random value and each sampler carries a threshold. A trace is kept when its random value passes the threshold. Because every service uses the same random value, a lower rate is always a subset of a higher rate. A service that keeps 10 percent keeps traces that every 50 percent service would also have kept.

Just as important, the threshold that was used is written into the trace state. That note tells later stages and the backend exactly how likely it was that this trace was kept, so they can count correctly later. We return to this in the chapter on honest math.

Simple Analogy

Imagine a raffle where every ticket has a number between 0 and 99. One stage keeps tickets under 50, another keeps tickets under 10. Anyone holding a ticket under 10 is kept by both stages, so the outcomes agree. If each stage instead drew its own random number, the same ticket could be kept by one and rejected by the other, and the trace would arrive in pieces.

Consistent probability sampling in more depth

Consistent probability sampling is one of the quieter but more important ideas in the OpenTelemetry sampling work, so it deserves a slower look. The goal is simple: when many stages each make their own keep-or-drop choice, the combined result should still be easy to reason about.

The trick is to separate two numbers. One is a randomness value that belongs to the trace. It is either carried along explicitly or taken from the random part of the trace identifier, depending on the version of the propagation rules in use. The other is a threshold that belongs to the sampler. A trace is kept when its randomness value is above the sampler’s threshold. A higher keep rate means a lower threshold, and a lower keep rate means a higher threshold.

Because the randomness value is shared by everybody, the kept sets are nested like Russian dolls. Every trace kept at 1 percent is also kept at 10 percent, and every trace kept at 10 percent is also kept at 50 percent. This is the property that lets you chain a coarse early stage with a finer later stage without shredding traces.

Finally, when a stage decides to keep a trace, it writes the threshold it used into the trace state. If a later stage uses an even higher threshold, it updates that note. At the end of the chain, the backend can read the final threshold and know the exact probability of survival, and therefore the exact weight each trace deserves. That note is what turns sampled traces from a loose pile of examples into a statistically meaningful sample.

!
Support Varies

Not every SDK, Collector component, or backend understands these probability notes yet, and parts of the specification have been maturing over time. Check what each piece of your own pipeline supports before you promise exact counts to your team.

Collector processors for sampling

Processor 1

Probabilistic sampler

Applies a percentage using the trace identifier, so it is cheap and consistent. It is a head-style decision made inside the Collector.

Processor 2

Tail sampling processor

Buffers whole traces and applies policies such as latency, status, attributes, span count, rate limit, and combinations of those.

Processor 3

Load balancing exporter

Routes all spans of one trace to the same downstream Collector, which tail sampling needs in order to see a complete trace.

Extension

Remote sampling extension

Lets the Collector serve sampling strategies to SDKs so rates can be changed centrally without redeploying applications.

Which of these are “dynamic”?

The tail sampling processor has a rate limiting policy and a composite policy that can divide a total budget among several sub-policies. Those give you budget-style adaptation inside the Collector. The remote sampling extension, which follows the model made popular by the Jaeger tracing system, lets a central place change what SDKs do. Fully automatic per-key rate adjustment, where an algorithm continuously retunes probabilities from live traffic, is typically supplied by a tracing backend, by a dedicated sampling proxy, or by custom code built around the processors above. Features and names change between releases, so always confirm details against the current OpenTelemetry documentation before you design around them.

Remote configuration channels

Changing rates at runtime needs a way to talk to running software. Two channels matter. One is the remote sampling approach where SDKs poll a central endpoint for their strategy at regular intervals. The other is OpAMP, the Open Agent Management Protocol, a standard being developed in the OpenTelemetry community for managing fleets of agents and Collectors, including pushing new configuration. Both let a control brain steer many data-plane workers.

flowchart TD
  C["Control brain (rate calculator)"] -->|"new strategies"| R["Remote sampling endpoint"]
  C -->|"new config"| O["OpAMP server"]
  R -->|"SDKs poll"| S1["Service A SDK"]
  R -->|"SDKs poll"| S2["Service B SDK"]
  O -->|"push or fetch"| G["Gateway Collectors"]
  S1 --> T["Telemetry stream"]
  S2 --> T
  G --> T
  T -->|"observed volume"| C
        
FIG 2 — A closed control loop: telemetry volume feeds the brain, the brain steers the samplers

6Inside an Adaptive Sampler

Now we open the engine and look at the moving parts, in words and pictures rather than code.

Step one: choose a key

An adaptive sampler rarely works on all traffic as one blob. It splits traffic into groups using a key, for example “service name plus operation name plus status”. Each key gets its own counter and its own probability. This is what allows a busy “view product” endpoint to be sampled hard while a rare “refund order” endpoint is sampled lightly, or even kept in full.

Step two: count in a time window

The sampler counts how many traces each key produced during a recent time window, for example the last 30 seconds. Counting is done with a smoothed average, often called an exponential moving average, which gives recent seconds more weight than old ones. This way a sudden spike is noticed quickly, but a single odd second does not make the system overreact.

Step three: compute the rate

Suppose the goal is to keep about 100 traces per second across the whole service. If the sampler estimates that 10,000 traces per second are arriving, the overall keep probability must be about 1 percent. If traffic falls to 500 per second, the probability rises to 20 percent. The sampler recalculates this every few seconds.

10,000/s
Traffic arriving at peak
100/s
Goal: traces kept per second
1%
Probability the sampler picks

Step four: share the budget fairly

If you simply gave every key the same percentage, the busiest key would still fill most of the budget. A fairer idea is to give each key a share that grows more slowly than its traffic. A common approach scales the number of kept traces with the square root, or with the logarithm, of each key’s volume. The effect is that a key with a hundred times more traffic gets only about ten times more samples, so rare keys keep a meaningful share.

Key (illustrative)Traffic per secondEqual percentage shareFairness-weighted share
View product8,000Almost the whole budgetA large but limited slice
Add to cart1,500A modest sliceA healthy slice
Checkout400A small sliceA strong slice
Refund order5Almost nothingOften kept in full

Step five: stamp the probability

Every kept trace must carry a note saying how likely it was to be kept. If a trace was kept at a 1 percent rate, that single trace stands in for about one hundred similar traces. This number is often called the adjusted count, and it is simply one divided by the probability. Without this stamp, any chart you draw from sampled data will lie to you.

Common algorithm families

Behind the friendly word “adaptive” there are several quite different ways to calculate the next probability. Knowing the families helps you read vendor documentation and decide what you actually need.

Family 1

Target-rate controller

Aims for a fixed number of kept traces per second for the whole service or for each key. It divides the target by the observed traffic to get the probability, then smooths the result.

Family 2

Moving-average sampler

Tracks the average volume of each key over recent windows and sets rates so that rarer keys receive proportionally more samples than frequent ones.

Family 3

Budget-pacing sampler

Looks at how much of a daily or monthly allowance has been used and gently lowers or raises the rate so the allowance lasts until the end of the period.

Family 4

Priority-based sampler

Gives each trace a score from signals such as errors, latency, and business importance, and keeps the highest-scoring traces first until the budget is filled.

These families can be mixed. A common recipe uses a priority layer for errors, a moving-average layer for fairness, and a budget-pacing layer as a safety net. The important point is that every family follows the same loop you just saw: observe, decide, apply, and record.

Cold start and warm-up

A freshly started sampler knows nothing. It has no history of traffic, so its first estimates are poor. If it guesses too low, it may drop traces it should have kept. If it guesses too high, it may flood the pipeline for a few seconds. Good designs handle this “cold start” on purpose. They begin with a safe default probability, they let the moving average fill up before trusting it, and they keep the first few minutes of rates conservative. After a restart, the same care applies, because every restart wipes the memory of the controller unless its state is stored somewhere.

The feedback loop

flowchart LR
  A["Incoming traces"] --> B["Count per key in time window"]
  B --> C["Smooth with moving average"]
  C --> D["Compare with goal"]
  D --> E["Compute new probability per key"]
  E --> F["Keep or drop new traces"]
  F --> G["Stamp probability on kept traces"]
  F --> B
        
FIG 3 — The observe, decide, apply loop of an adaptive sampler
i
Design Tip

Always give every key a minimum probability, called a floor, so that a rare key is never driven all the way to zero. Also cap how fast a probability may change in one step. A controller without limits can swing wildly, like a driver who yanks the steering wheel at every small bump.

7Choosing What to Adapt On

The quality of an adaptive sampler depends less on its maths and more on the signals and keys you feed it.

Signals that describe a trace

An adaptive sampler can only react to things it can see. In head sampling, that means information known at the start. In tail sampling, it also includes the outcome. Choosing the right signals is a design decision, and different signals protect different goals.

Signal 1

Service and operation

The most common key. It separates a hot endpoint from a rare one and is nearly always available at the start of a trace.

Signal 2

Status or error flag

Failed requests are precious. Tail sampling can keep nearly all of them, while head sampling can only guess from early hints.

Signal 3

Latency

Slow traces reveal bottlenecks. Only tail sampling can use this directly because duration is unknown until the end.

Signal 4

Customer or tenant tier

Lets you protect premium or small customers from being drowned out by a few huge ones. Be careful about privacy when using it.

Signal 5

Trace shape

Span count, number of services touched, or unusual call paths can mark a trace as strange and worth keeping.

Signal 6

Business importance

Checkout, payment, or sign-up flows may deserve higher rates than a browsing page, even when volume is similar.

The danger of too many keys

Every key costs memory because the sampler must remember counters for it. If you build keys from values that almost never repeat, such as user identifiers, request identifiers, or full web addresses with query strings, the number of keys explodes. This problem is called high cardinality. It wastes memory, slows the sampler, and makes every individual key so rare that the algorithm cannot learn a stable rate.

Simple Analogy

If a school teacher tried to keep a separate notebook for every possible combination of a student’s name, shoe size, and lunch order, the shelf would collapse. A teacher keeps notebooks per class instead. Good sampling keys are like classes: few enough to manage, meaningful enough to matter.

!
Common Mistake

Using the raw URL path as a key. A path like an order lookup contains a different number on every call, so every request becomes its own key. Use the route template instead, the pattern that groups all order lookups together.

A worked example of key design

Let us design keys for an imaginary online bookshop with six services. The team first tries the key “service plus full URL”. Within a day the sampler tracks tens of thousands of keys, because every book page and every order has its own address. Memory climbs, and most keys have seen only one request, so no rate can be learned.

The team then moves to “service plus route template plus status class”. Now a book page becomes one route template, an order lookup becomes another, and status class groups results into success, client error, and server error. The number of keys falls to a few hundred, each with plenty of traffic to learn from.

Candidate keyApproximate key countVerdict
Service name onlySixToo coarse, hides rare operations inside busy services
Service plus route templateDozensGood starting point
Service plus route template plus status classA few hundredBest balance for most teams
Previous key plus tenant tierSeveral hundred to a thousandUseful when fairness across customers matters
Service plus full URLTens of thousands and growingAvoid, cardinality explosion
Anything including user or session identifiersUnboundedNever use as a key

The lesson is that key design is a negotiation between precision and stability. Add detail only when you can show that a missing detail hides an important group, and remove detail when you see keys that rarely receive traffic.

Combining a base rule with exceptions

Mature systems rarely use one sampler alone. They layer rules in priority order. First comes a “must keep” layer for errors, very slow traces, and flagged debugging sessions. Next comes a fairness layer that gives rare keys a guaranteed minimum. Last comes the adaptive layer that fills the remaining budget from everything else. Thinking in layers keeps each rule simple and easy to explain to the team.

8Architecture Patterns

There is no single correct place to put an adaptive sampler. Here are the three shapes you will meet most often.

Pattern A: SDK head sampling with central control

Each application’s SDK runs a head sampler. A central service decides the rates and publishes them as strategies. The SDKs poll for updates every minute or so and switch to the new strategy. Because the decision happens at the start, dropped traces cost almost nothing. The limitation is the same as any head design: the sampler cannot see errors or latency that have not happened yet.

flowchart LR
  subgraph Apps["Applications"]
    A1["Service A SDK sampler"]
    A2["Service B SDK sampler"]
  end
  CTRL["Central strategy service"] -->|"poll every minute"| A1
  CTRL -->|"poll every minute"| A2
  A1 -->|"kept traces only"| COL["Collector"]
  A2 -->|"kept traces only"| COL
  COL --> BE["Backend"]
  BE -->|"volume statistics"| CTRL
        
FIG 4 — Pattern A: SDK samplers steered by a central strategy service

Pattern B: Two-tier Collector with tail sampling

Applications send everything to a first layer of Collectors, often running next to the applications as agents. That layer forwards spans to a second layer, the gateway, using a routing step that sends every span of the same trace to the same gateway instance. The gateway holds traces briefly, applies tail policies, and exports the survivors. The routing step is the secret that makes tail sampling work when you have more than one gateway.

flowchart LR
  S["Services"] --> AG["Agent Collectors"]
  AG --> LB["Load balancing by trace ID"]
  LB --> GW1["Gateway 1 with tail sampling"]
  LB --> GW2["Gateway 2 with tail sampling"]
  LB --> GW3["Gateway 3 with tail sampling"]
  GW1 --> BE["Backend"]
  GW2 --> BE
  GW3 --> BE
        
FIG 5 — Pattern B: trace-aware routing so each gateway sees whole traces

Pattern C: Hybrid, a coarse head filter then adaptive tail

Pure tail sampling sends everything over the network, which can be costly. A hybrid design applies a gentle head sampler first, perhaps keeping a quarter of traces, to cut the firehose. It then uses tail sampling on what remains, with adaptive rates to meet the budget and always-keep rules for errors. The catch is that the head stage may already have dropped some interesting traces, so teams often exempt known-critical services from the head filter.

PatternStrengthWeaknessBest fit
A: SDK plus central controlLowest overhead, simple data pathCannot see outcomesVery high volume with modest needs
B: Two-tier tail samplingKeeps errors and slow traces reliablyMemory, routing, and scaling effortTeams that must never miss a failure
C: HybridBalances cost and smartnessEarly drops may hide rare eventsLarge estates with tight budgets

Where should the sampler physically run?

Besides choosing a pattern, you must choose where each component runs. Three placements are common, and each shifts cost and risk to a different place.

Placement 1

Inside the application

Cheapest for the network and the best at avoiding wasted work, but every language SDK must support the sampler you want, and changes need rollouts or remote configuration.

Placement 2

Agent next to the application

A Collector on the same machine or in the same pod absorbs spans quickly and can apply light filtering. It keeps applications simple but adds one more process to every host.

Placement 3

Central gateway tier

The best place for tail sampling because it can see whole traces and be scaled independently. It becomes a critical shared service that needs careful capacity planning.

Placement 4

Backend or vendor side

Some platforms apply their own sampling after ingestion. This is easy to adopt, but you pay for the network and ingestion first and have less control over the rules.

Many clusters and many regions

Large organisations rarely run one cluster. If services in different regions take part in the same trace, the spans of that trace can start in different places. A tail-sampling design then faces a choice: send every span to a single central region, which costs bandwidth and adds delay, or make decisions locally and accept that some cross-region traces will be incomplete.

A common compromise is to keep most traces within their home region, since most requests never cross a region border, and to use a lightweight head decision for the few that do. Teams should measure what share of traces really cross regions before paying for a complicated design. Often the answer is small enough that a simple approach is good enough.

i
Practical Tip

Start with Pattern A or a simple fixed tail policy. Move to Pattern B or C only when you can name the specific question you cannot answer today. Complexity you do not need is a cost you pay every on-call night.

9Data Flow and Lifecycle of a Sampled Trace

Follow one trace from the first click to the moment the sampler keeps or drops it.

A trace through a tail-sampling pipeline

Let us walk through Pattern B with a single shopping request. The story shows where time is spent, where memory is used, and where decisions happen.

sequenceDiagram
  participant U as User
  participant G as Web gateway service
  participant P as Payment service
  participant A as Agent Collector
  participant T as Tail sampling gateway
  participant B as Backend
  U->>G: Click pay
  G->>P: Call with trace context
  P-->>G: Error returned
  G-->>U: Failure shown
  G->>A: Send spans
  P->>A: Send spans
  A->>T: Route by trace ID
  T->>T: Buffer and wait for late spans
  T->>T: Apply policies and current rates
  T->>B: Keep trace and stamp probability
        
FIG 6 — Lifecycle of one failed request under tail sampling

The lifecycle in plain steps

1

Spans are created everywhere

Each service records its own spans and sends them out as they finish. Services do not wait for each other and do not know the final outcome of the whole trace.

2

Spans are routed together

The routing layer hashes the trace identifier so that all spans of that trace land on the same gateway instance.

3

The gateway waits

It buffers spans for a configured waiting period, a guess at how long the slowest part of a trace could take. This is the main source of both memory use and added delay.

4

Policies run

Always-keep rules look for errors and extreme latency. Adaptive rules then decide about everything else using the current per-key probability.

5

Decision is cached

The gateway remembers the decision for a while. If a late span arrives after the decision, it is treated consistently with the rest of its trace instead of being decided afresh.

6

Export and statistics

Kept traces are exported with their sampling probability. Counters for kept and dropped traces are fed back to the rate calculator for the next cycle.

When things go wrong in the pipeline

A tail-sampling pipeline is a chain of machines, and chains break. Planning for the breaks is part of the design, not an afterthought. Four failure stories are worth knowing.

First, a gateway instance restarts. Everything it was holding in memory is gone, which means the traces that were waiting for a decision vanish. The loss is usually small, but during a rolling update it can repeat several times, so schedule updates for calm periods and update one instance at a time.

Second, the gateway runs short of memory. A well-built system starts discarding the oldest or least interesting traces on purpose instead of crashing. You want this behaviour to be visible in your metrics so that you know when it happens.

Third, the set of gateway instances changes because of scaling. When an instance is added or removed, the routing layer sends some traces to a different instance halfway through their life. Those traces may be judged on partial information. This is a known cost of scaling tail sampling, and it is a good reason to scale in small, planned steps.

Fourth, clocks disagree. Services on different machines may record slightly different times, which can make a trace look longer, shorter, or even out of order. Keep machine clocks synchronised and avoid latency rules so tight that a small clock difference changes the outcome.

!
Plan for Partial Data

No sampling pipeline sees every trace perfectly. Design your rules and your dashboards so that a small share of incomplete traces is harmless, and measure that share so it never grows unnoticed.

Queues, back-pressure, and overload

Between each pair of stages in a pipeline sits a queue that absorbs short bursts. When the next stage is slow, the queue grows. If it grows too long, something must give: the pipeline can refuse new data, slow down the sender, or drop spans. Each choice has a cost, and the right one depends on how much you value completeness against how much you value the health of your applications.

Most teams choose to protect the applications first. The Collector should refuse or drop data rather than push pressure back into a customer-facing service. When the pipeline does drop data under overload, it is much better to drop whole traces than random spans, because a trace with missing spans is confusing and a missing trace is simply absent. Counting these overload drops separately from deliberate sampling drops tells you whether a gap in the data was a design decision or a symptom of trouble.

The waiting-period dilemma

The waiting period is a trade-off with no perfect answer. If it is too short, long traces are judged before their slow spans arrive, and the sampler may drop a trace that would have been marked slow. If it is too long, memory use rises and traces appear in your backend later than people expect. Most teams measure the real length of their longest common traces and set the wait just above it, then watch a metric that counts spans arriving after their trace was already decided.

Simple Analogy

A teacher marking an exam must decide how long to wait for students who are still writing. Collect the papers too early and unfinished answers are marked wrong. Wait too long and the whole class sits idle. The best teachers know how long the exam usually takes and add a small safety margin.

10Keeping the Math Honest

Sampling saves money but can quietly poison your charts. This chapter explains how to avoid that.

The problem of biased counts

Suppose you keep 1 percent of ordinary requests and 100 percent of failed requests. If you count the traces in your backend, errors will look enormously more common than they really are. The sample is deliberately unfair, and any statistic computed from it without correction will be wrong.

Adjusted counts

The fix is to give each kept trace a weight equal to one divided by its keep probability. An ordinary trace kept at 1 percent counts as a hundred. A failed trace kept at 100 percent counts as one. When you add up the weights instead of the raw rows, the totals match reality. This is why every adaptive sampler must record the probability it used. If the rate changes every few seconds, the weights change too, and only a per-trace stamp can keep the sums correct.

1%
Keep probability for ordinary traces
×100
Weight each kept ordinary trace carries
100%
Keep probability for errors, weight of one

Compute rate, error, and duration metrics before sampling

The safest way to protect your dashboards is to compute headline metrics from all the data, before any trace is dropped. In a Collector, a component that turns spans into metrics can sit ahead of the sampling stage so request counts, error rates, and latency distributions reflect every request. Sampled traces then play their proper role: they are the evidence you open when a metric looks wrong, not the source of the metric itself.

flowchart LR
  IN["All incoming spans"] --> SM["Span to metrics conversion"]
  IN --> SP["Sampling stage"]
  SM --> MB["Metrics backend with full counts"]
  SP --> TB["Trace backend with kept traces"]
        
FIG 7 — Derive metrics from everything, keep only some traces
!
Common Mistake

Building an error-rate dashboard by counting stored traces. With adaptive sampling the ratio of stored errors to stored successes is intentionally distorted, so the graph will show a scary spike that does not exist in real life.

A worked example with weights

Let us put numbers on the idea. Imagine that during one minute a service handles 60,000 requests. Of those, 59,400 succeed and 600 fail. The sampler keeps every failure, so 600 failed traces are stored, each with weight one. It keeps 1 percent of successes, so about 594 successful traces are stored, each with weight one hundred.

If you count stored rows, you see 600 failures and 594 successes, which suggests that almost half of all requests fail. That reading is badly wrong. Now add up the weights instead. Failures contribute 600 times one, which is 600. Successes contribute 594 times one hundred, which is 59,400. The weighted view says that 600 out of 60,000 requests failed, which is exactly one percent, and matches reality.

1,194
Stored traces in the sample
~50%
Apparent failure share from raw rows
1%
True failure share from weighted counts

This small calculation is the reason adaptive sampling and honest dashboards must travel together. A backend that understands weights can do the correction for you. A backend that does not should never be used to calculate rates from sampled traces.

Statistical honesty about small samples

Adjusted counts give the right average, but they do not give certainty. If a key was sampled at 0.1 percent and only three traces were kept, the estimate “three thousand requests” has a wide margin of error. Adaptive samplers help here because they raise rates for quiet keys, which gives those keys enough samples for reliable estimates. Still, tell your readers when a number comes from a thin sample.

“If you cannot say how likely a trace was to be kept, you cannot say how common it really is.”

Rate changes and the staircase effect

Because the rate changes over time, a graph of kept traces per second is a poor picture of real traffic. It may stay flat while real traffic triples, because the sampler is working hard to keep the output steady. Always plot weighted counts, not raw kept counts, when you want to see demand.

11Advantages, Disadvantages, and Trade-offs

Adaptive sampling is powerful, but it is not free. A balanced view helps you decide when it is worth the effort.

Advantages

  • Predictable cost, because the output volume follows a budget even when traffic spikes
  • Better visibility for rare operations, since fairness rules protect quiet keys
  • Errors and slow traces are kept reliably when tail policies are used
  • Less manual tuning, because nobody edits percentages for every traffic change
  • Faster incident response, because the useful traces are already stored
  • Central control means rates can change without redeploying applications

Disadvantages / Trade-offs

  • More moving parts: counters, controllers, routing layers, and control channels can all fail
  • Tail sampling needs memory and careful scaling, and it adds delay before traces appear
  • Rates that change over time make raw numbers harder to interpret
  • Mistakes in key design can starve some groups or blow up memory
  • Debugging is harder when two identical requests were treated differently on purpose
  • Learning curve for teams who are new to the maths of weighted counts

Adaptive versus fixed, side by side

AspectFixed samplingAdaptive sampling
Behaviour under traffic spikesVolume spikes with trafficVolume stays near the target
Behaviour in quiet periodsVery few traces surviveRates rise so you still get data
Rare operationsOften invisibleProtected by fairness rules
Setup effortMinutesDays to weeks, plus ongoing care
Predictability of billsLow, follows trafficHigh, follows the budget
ExplainabilityOne numberA policy and a control loop

When adaptive sampling is not worth it

Adaptive sampling is not a badge of maturity. For many teams, a simpler approach is the better engineering choice. Consider staying with fixed sampling when your volume is small and your bill is comfortable, when traffic is steady enough that a fixed percentage works all year, when your team is small and cannot afford another system to operate, or when your questions can be answered from metrics and logs and traces are only an occasional extra.

A good test is to ask what decision the extra complexity will improve. If nobody can name a question that the adaptive design will answer and the fixed design cannot, wait. Systems that are simple are easier to debug at three in the morning, and that has real value.

Simple Analogy

A fixed rule is like a manual car gearbox with only one gear. It is simple and cheap, but terrible on hills. Adaptive sampling is an automatic gearbox: smoother on every road, but with more parts that can need repair.

12Security, Compliance, and Watching the Sampler Itself

A system that decides what you remember must itself be protected, measured, and trusted.

Security considerations

Risk 1

Sensitive data in buffers

Tail sampling holds raw spans in memory before filtering. Remove or mask personal data before it reaches the buffer, not after.

Risk 2

Control channel abuse

If anyone can push new sampling rates, an attacker could drop all traces to hide an attack, or raise rates to 100 percent to cause a cost explosion. Protect the channel with authentication and encryption.

Risk 3

Attribute-driven manipulation

If a rule keeps every trace with a certain header, outsiders can send that header on every request and flood your storage. Treat user-controlled values as untrusted.

Risk 4

Data retention rules

Kept traces may contain regulated information. Sampling does not remove your duty to follow retention and deletion policies.

Compliance and privacy

Sampling is sometimes mistaken for anonymisation. It is not. A trace that is kept is kept in full, with every attribute it carries. If a rule says “always keep traces for this customer”, that customer’s data is being stored more heavily than others, which may matter for privacy reviews. Document your keep rules the same way you document any other data processing.

Governance: who owns the sampling policy?

Sampling rules decide what the organisation will be able to see during its worst day, so they should not be an accident of whoever edited a file last. Healthy teams treat the sampling policy as a shared product with a named owner, usually the platform or observability team, and with input from the engineers who rely on the traces.

Write the policy in plain language: which traces are always kept, which services receive guaranteed floors, what the total budget is, and what the fallback behaviour is. Store the machine-readable version in the same place as other configuration, require review for changes, and keep a history so that you can answer the question “what were the rules on the day of the incident?”

Finally, make it easy for engineers to ask for exceptions. If a team is launching a risky feature, they should be able to request a temporary higher rate through a simple process that expires on its own. Without an easy path, teams invent their own workarounds, and the central design slowly loses control.

Monitoring the sampler

An adaptive sampler is a control system, and control systems need instruments. The following signals tell you whether it is healthy.

1

Kept versus dropped counts

Track both, per key where practical. A sudden drop in kept traces for an important key is an early warning.

2

Current probability per key

Watch how the rates move. A probability pinned at its floor or ceiling for hours suggests the goal is badly set.

3

Late and orphan spans

Count spans that arrive after their trace was decided. High numbers mean the waiting period is too short or routing is broken.

4

Buffer size and memory

Track how many traces are held and how much memory they use. Set safety limits so a traffic spike drops data gracefully instead of crashing the Collector.

5

Control loop health

Measure how fresh the strategies are and how often SDKs fail to fetch them. Define a safe fallback rate for when the control brain is unreachable.

Capacity planning for tail sampling

Because tail sampling holds traces in memory, you can estimate the machine size you need with simple arithmetic. Take the number of new traces arriving each second, multiply by the waiting period in seconds, and you get the number of traces held at any moment. Multiply that by the average size of a trace and you have the raw memory need. Then add a generous safety margin, because spans carry extra overhead inside the program and traffic is never perfectly smooth.

Here is an illustrative example. Suppose 2,000 new traces arrive every second, each with about 30 spans of roughly one kilobyte, and the gateway waits 30 seconds. That means about 60,000 traces are held at once, and at around 30 kilobytes each the raw buffer is close to 2 gigabytes. With overhead and headroom, a team would plan for several times that amount, spread over more than one instance.

2,000/s
New traces arriving (illustrative)
30 s
Waiting period before deciding
~2 GB
Raw buffer before safety margin

The same arithmetic shows why shortening the wait or applying a gentle head filter first has such a large effect: both reduce the number of traces in the buffer directly. It also shows why a sudden growth in span count per trace, perhaps after a new feature adds many database calls, can quietly double your memory need.

i
Reliability Tip

Decide in advance what happens when things go wrong. Fail towards a modest fixed rate, not towards “drop everything” and not towards “keep everything”. A quiet, predictable fallback is far safer than a surprise in either direction.

13Design Patterns and Anti-patterns

Teams keep rediscovering the same good ideas and the same expensive mistakes. Here they are, named.

Patterns worth copying

Keep-all-errors, adapt-the-rest

Always keep failed and very slow traces through a high-priority rule, then let the adaptive layer share the remaining budget across everything else. This protects the most valuable traces from being traded away during a traffic spike.

Per-key floor with a global ceiling

Give every key a small guaranteed minimum and cap the total output. Rare operations never vanish, and the bill never explodes.

Metrics first, traces second

Generate counts, error rates, and latency histograms from all spans before sampling. Use traces as sampled examples that explain the metrics.

Parent-based consistency

Wrap every head sampler so that downstream services honour the upstream decision. This keeps traces whole across service boundaries.

Staged rollout of rate changes

Apply new strategies to a small share of services first, watch the sampler’s own health signals, and widen only when they look steady.

Debug override

Provide a controlled way for an engineer to force full sampling for one request or one session while investigating a problem, with an automatic expiry.

Shadow mode before enforcement

Run a new sampling policy beside the old one, record what it would have kept, and compare the results before letting it drop anything. This reveals surprises while they are still free.

Tiered retention

Keep errors and slow traces for a long time, ordinary kept traces for a short time. Retention becomes another dial that makes the budget go further without losing the most useful evidence.

Visible sampling decisions

Record on each kept trace which rule kept it and at what probability. Engineers can then see at a glance whether a trace was kept because it failed or because it was a routine sample.

Anti-patterns to avoid

ANTI-PATTERN-01 Avoid
Problem

Several gateway Collectors apply tail sampling, but spans of one trace are spread across them by plain round-robin distribution.

Why It’s Harmful

Each gateway sees only a fragment of every trace. An error span may be judged by a gateway that never saw the slow span, so decisions are wrong and traces arrive in the backend with holes.

Correct Approach

Place a trace-aware routing layer in front of the gateways so all spans sharing a trace identifier reach the same instance. Scale by adding instances behind that router.

ANTI-PATTERN-02 Avoid
Problem

Dashboards for request rate and error rate are built by counting traces stored in the tracing backend.

Why It’s Harmful

Adaptive and priority-based sampling intentionally distorts the mix of stored traces. The dashboard shows numbers that move because the sampler moved, not because users behaved differently.

Correct Approach

Derive metrics from complete data before sampling, or weight stored traces by the inverse of their keep probability.

ANTI-PATTERN-03 Avoid
Problem

The sampling key includes values with huge variety, such as full URLs with identifiers, user identifiers, or session identifiers.

Why It’s Harmful

Memory grows without limit, each key is too rare to learn a stable rate, and the sampler effectively behaves as if no keys existed while still paying the cost of tracking them.

Correct Approach

Use low-cardinality keys such as service, route template, and status class. Cap the number of tracked keys and fold the overflow into a shared bucket.

ANTI-PATTERN-04 Avoid
Problem

Every service in a call chain runs its own independent random sampler instead of respecting the parent’s decision.

Why It’s Harmful

The chance that every service in a chain keeps the same trace becomes the product of their individual probabilities. Most traces end up fragmented, which makes them nearly useless for finding the cause of a problem.

Correct Approach

Decide once at the root, propagate the decision, and let child services follow it. Where several stages must sample, use consistent probability methods so lower rates are always subsets of higher ones.

ANTI-PATTERN-05 Avoid
Problem

The controller recalculates rates with no smoothing, no floor, and no limit on how fast a rate may change.

Why It’s Harmful

A short burst of traffic can push a rate to nearly zero, and the following quiet moment can push it back to 100 percent. The output oscillates, costs jump around, and important keys flicker in and out of visibility.

Correct Approach

Smooth observations over time, set minimum and maximum probabilities, and limit the size of each step so the system settles gently.

14Best Practices and Common Mistakes

A practical checklist, grouped by the stage of your journey.

Before you start

  • Name your questions. Write down the three or four questions traces must answer, such as “why was this checkout slow” or “which release broke payments”. Sampling rules should protect those answers.
  • Measure your current volume. Know spans per second, spans per trace, and the cost per million spans. Without a baseline you cannot prove improvement.
  • Decide your budget. Pick a target in traces per second or in cost per day. An adaptive sampler needs a goal to chase.

While you build

  • Use parent-based decisions everywhere so traces stay whole.
  • Layer your rules. Must-keep first, fairness second, adaptive third.
  • Stamp the probability on every kept trace so counts can be corrected.
  • Keep keys small and stable. Prefer route templates and status classes.
  • Add safety limits. Cap memory, cap tracked keys, and define a fallback rate.
  • Redact sensitive attributes before data reaches any buffer.

After you launch

  • Monitor the sampler with the signals from the monitoring chapter.
  • Review key lists regularly. New services and routes appear all the time, and old rules go stale.
  • Test with game days. Simulate a traffic spike and a control-channel outage and confirm the system behaves as designed.
  • Teach your team that stored traces are samples, and show them how weighted counts work.

A vocabulary cheat sheet

Sampling conversations go wrong quickly when two people use the same word for different things. Agree on these terms as a team and your design discussions will be shorter and calmer.

Term

Sampling probability

The chance, between zero and one, that a particular trace is kept. Ordinary traces might have 0.01, errors might have 1.

Term

Adjusted count

One divided by the probability. It tells you how many real requests a single kept trace stands for.

Term

Key

The label that groups traces for counting, such as service plus route template plus status class.

Term

Floor and ceiling

The smallest and largest probabilities a key may receive. They stop rare keys disappearing and busy keys exploding.

Term

Decision wait

How long a tail-sampling gateway holds a trace before judging it, chosen to cover the slowest normal trace.

Term

Budget

The target volume of kept traces, expressed per second, per day, or as a cost, which the adaptive controller tries to honour.

Team habits that keep sampling healthy

  • Review the dropped data, not just the kept data. Occasionally inspect a sample of what the sampler discarded and confirm it really was boring.
  • Write down the budget and the reasons for it. When finance asks why the tracing bill changed, the answer should be in a document, not in someone’s memory.
  • Keep a dashboard for the sampler. The same people who watch service health should be able to see sampler health at a glance.
  • Include sampling in incident reviews. After every serious incident, ask whether the sampler kept the traces that would have helped, and tune the rules if it did not.
  • Teach new engineers early. A short onboarding note on “traces are samples, metrics are complete” prevents a whole class of confusion.
!
Common Mistakes at a Glance

Treating sampling as a one-time setting, forgetting to propagate the decision, building dashboards from stored traces, letting key cardinality grow unchecked, scaling tail sampling without trace-aware routing, and having no fallback when the control brain disappears.

i
Version Awareness

Sampling components in OpenTelemetry evolve. Some pieces are stable, others are still marked as experimental or under active development, and option names change. Check the current documentation and release notes of your SDK and Collector version before relying on a specific behaviour.

15Real-World and Industry Examples

How the ideas show up in practice, from open-source tools to typical company situations.

Tools and ecosystems

Jaeger and adaptive sampling

The Jaeger tracing project popularised remote sampling strategies, where SDKs fetch their rules from a central endpoint. Its backend has also offered an adaptive mode that adjusts probabilities per service and operation to aim for a target number of samples. Newer Jaeger releases are built on top of the OpenTelemetry Collector, which shows how closely these ideas are now connected.

Honeycomb and its sampling proxy

Honeycomb’s open-source sampling proxy, called Refinery, applies tail-style decisions and offers dynamic samplers that adjust rates by key so that rare events are kept more often. It is a well-known example of the “dedicated sampling tier” approach.

OpenTelemetry Collector tail sampling

Many organisations build their own adaptive behaviour from the Collector’s tail sampling policies, rate limits, and composite budgets, combined with trace-aware routing. This keeps the data path inside open standards.

Commercial observability platforms

Several commercial products offer their own intelligent or dynamic sampling features on top of OpenTelemetry data. Their exact algorithms differ, so compare how each one handles errors, fairness, and weighted counts before you adopt one.

Questions to ask before choosing a product

If you decide to buy rather than build, a short list of questions will quickly separate serious products from marketing language.

  • Does it keep all errors and slow traces? Ask how it defines “slow” and whether the definition adapts per operation.
  • Does it record the sampling probability? If not, ask how it keeps counts honest.
  • How does it share the budget between keys? Look for floors, fairness rules, and caps on key count.
  • What happens during overload or when its control service is unreachable? You want a calm, documented fallback.
  • Where does it run and what does it need in memory? Tail sampling at scale needs real capacity.
  • Can you see why a trace was kept or dropped? Transparency is essential for trust and for debugging.
  • Does it work with standard OpenTelemetry data and propagation? Lock-in is a hidden cost that grows over time.

Typical situations (illustrative)

Online shop during a flash sale

Traffic jumps tenfold in minutes. A fixed 5 percent rate would multiply storage costs overnight. An adaptive sampler lowers the rate for browsing pages, holds checkout and payment at higher rates, and keeps every failed payment, so the team stays within budget and still sees every problem that matters.

Multi-tenant software product

A few huge customers generate most traffic, and many small customers generate very little. Fairness-weighted keys by tenant tier make sure small customers still produce traces, so support engineers can investigate their complaints.

Overnight batch and quiet periods

At night traffic falls to a trickle. The adaptive sampler raises its rate towards 100 percent, giving the team plenty of examples when they inspect the quiet hours without paying more, since the volume is naturally small.

Gradual rollout of a new release

A new version of a service starts with a small share of traffic. A key that includes the version number lets the sampler give the new release a healthy sample rate even while it handles little traffic, so regressions show up early.

16Frequently Asked Questions

Short, direct answers to the questions people ask most often.

Q1Is adaptive sampling a built-in switch in OpenTelemetry?

Not as a single switch. OpenTelemetry supplies samplers, probability fields in the trace state, a probabilistic sampler processor, a tail sampling processor, a trace-aware load balancing exporter, and channels for remote configuration. Fully automatic per-key rate adjustment is usually provided by a backend, a sampling proxy, or custom logic built on these parts.

Q2Can head sampling be adaptive?

Yes. A central service can watch volume and publish new rates that SDKs fetch regularly. The decision still happens at the start of the trace, so it cannot use errors or latency, but it can adapt to traffic levels and to different keys such as the operation name.

Q3Can tail sampling be adaptive?

Yes, and that is where adaptive designs are most powerful. The gateway can keep all errors and slow traces and adjust the rate for everything else to meet a budget. The rate limiting and composite policies of the tail sampling processor give simple budget control, and custom or external controllers can add per-key adjustment.

Q4Why must all spans of a trace reach the same Collector?

Because the decision is based on the complete trace. If spans of one trace are split across instances, each instance sees only a part, and rules about total duration, errors anywhere in the trace, or span counts give wrong answers.

Q5Will sampling make my metrics wrong?

Only if you compute metrics from the sampled traces without correction. Generate metrics from all data before sampling, or weight each kept trace by one divided by its keep probability. Either approach keeps totals honest.

Q6How much of my traffic should I keep?

There is no universal number. Start from your budget and your questions. Many teams keep all errors, a strong share of critical flows, and a small percentage of routine traffic. Adaptive sampling is useful precisely because the right percentage changes with load.

Q7What happens if the control service or remote configuration source goes down?

SDKs and Collectors should keep using their last known strategy for a while and then fall back to a safe default rate that you chose in advance. Avoid fallbacks that drop everything or keep everything, because both create unpleasant surprises.

Q8Does sampling affect logs and metrics too?

Trace sampling affects traces. Logs and metrics follow their own rules. A helpful habit is to link logs to trace identifiers and to record the sampled flag, so you can tell whether a matching trace should exist in your backend.

Q9Is tail sampling always better than head sampling?

No. Tail sampling is smarter but costs more in network, memory, and operations. Head sampling is cheap and simple. Many teams combine them, and some stay with head sampling because their questions do not require outcome-based selection.

Q10How do I know my sampler is working well?

Check that output volume stays near the target, that important keys always have traces, that late and orphan spans are rare, that memory stays inside limits, and that weighted counts from sampled data agree with metrics computed from full data. If those hold, the sampler is doing its job.

Q11Does adaptive sampling add delay to my applications?

Head-style samplers inside the SDK add a very small calculation per trace, usually unnoticeable. Tail sampling does not slow the request itself, but it does delay when a trace becomes visible in your backend, because the gateway waits before deciding.

Q12Should I sample logs and metrics the same way as traces?

Usually not. Metrics are small and valuable, so most teams keep them complete. Logs can be filtered by their own rules, and a useful habit is to keep logs that belong to kept traces so that the two tell a matching story.

Q13Can I force a trace to be kept while debugging?

Yes, and you should plan for it. A common approach is a special marker, such as a debug flag, that a trusted tool adds to a request and that a high-priority rule recognises. Make sure outsiders cannot set the marker on public traffic and that the override expires automatically.

Q14What is the smallest useful step towards adaptive sampling?

Move your headline metrics so that they are computed before sampling, switch to parent-based head sampling, and add a rule that keeps errors. These three steps deliver most of the value, and each can be rolled back on its own.

17A Practical Adoption Roadmap

You do not need to build everything at once. This roadmap moves from safe and simple to advanced, so each stage pays for itself before the next begins.

Six stages from fixed to adaptive

1

Measure the baseline

Record spans per second, traces per second, average trace size, and the monthly cost of your tracing backend. Note which questions engineers have been unable to answer with the traces they have today.

2

Use parent-based head sampling

Switch every service to a parent-based sampler with a modest fixed probability. This alone keeps traces whole and gives you a stable foundation to build on.

3

Move metrics ahead of sampling

Generate request counts, error rates, and latency distributions from all spans before any are dropped. From this point your dashboards no longer depend on how many traces you keep.

4

Add outcome-based rules

Introduce a tail-sampling gateway with trace-aware routing. Start with simple rules: keep errors, keep very slow traces, and keep a small share of the rest. Run it beside the old path first and compare results.

5

Make the rest adaptive

Replace the fixed share with a controller that targets a trace budget, protects rare keys with floors, and stamps the probability on every kept trace. Roll it out service by service.

6

Operate and refine

Watch the sampler’s own health signals, review the key list every quarter, rehearse failure scenarios, and adjust the budget as the business grows.

How mature is your setup?

LevelWhat it looks likeTypical risk
Level 0: Keep everythingNo sampling, all traces storedCost grows with traffic and nobody can afford long retention
Level 1: Fixed percentageOne probability for all servicesRare operations and errors are missed
Level 2: Outcome-awareTail rules keep errors and slow tracesMemory pressure and routing mistakes
Level 3: AdaptiveRates follow a budget and fairness rulesController instability if limits are missing
Level 4: GovernedAdaptive sampling with monitoring, fallbacks, and regular reviewSlow drift if reviews are skipped
Simple Analogy

Learning to drive does not begin on a motorway at night. You start in an empty car park, then quiet streets, then busier roads. Each stage builds a skill the next stage needs. Adopting adaptive sampling works the same way, and skipping stages is how teams end up in a ditch.

How to decide you are ready for the next stage

Move forward only when the current stage is boring. If the sampler’s own metrics are steady, if engineers trust the traces they find, and if the monthly bill matches the forecast, you are ready. If any of those three is shaky, fix it first. A calm foundation makes every later improvement easier to measure and easier to roll back.

i
Roll Back Easily

At every stage, keep a way to return to the previous behaviour within minutes. A switch that restores a simple fixed rate is the best insurance you can buy when a new rule behaves in an unexpected way.

18A Day in the Life of an Adaptive Sampler

To make everything concrete, let us follow an imaginary adaptive sampler through one full day at an online shop. The numbers are illustrative, not measurements.

The setup

The shop runs a two-tier Collector design with a tail-sampling gateway. The team has set a budget of about 150 kept traces per second. Errors and very slow traces are always kept and do not count against the adaptive share. Every key has a floor, so no operation ever falls to zero, and every kept trace carries its probability.

1

3 a.m., the quiet hours

Only about 120 traces per second arrive. The controller sees that the budget is larger than the traffic, so it raises the keep probability for ordinary traces close to the maximum. Engineers who look at night traffic find plenty of examples, and the cost is tiny because volume is low.

2

9 a.m., the morning ramp

Traffic climbs to around 3,000 traces per second. The controller lowers probabilities step by step, never by more than its limit, so the output stays near budget without sudden jumps. Rare keys such as refunds stay near their floors or are kept in full.

3

12 noon, the flash sale

Traffic leaps to 20,000 traces per second within minutes. A fixed one percent rate would have sent 200 traces per second to storage, above budget and growing. The adaptive sampler drops browsing pages to a tiny probability, holds checkout higher, and the bill stays flat.

4

12:07 p.m., a payment provider slows down

Payment calls begin to take several seconds and some fail. The always-keep rules capture the slow and failed traces, so engineers see the full chain of calls almost at once. Meanwhile, the metrics computed before sampling show the error rate rising correctly.

5

2 p.m., recovery

The provider recovers and traffic settles. The controller raises probabilities again, gradually. The team reviews the sampler’s own dashboard and confirms that kept volume stayed near budget and that no important key lost its floor.

6

11 p.m., the nightly batch

A scheduled job produces a short burst of unusual traces from a rarely used service. Because that key has a floor and a small volume, nearly every trace is kept, and the team has examples if the job ever misbehaves.

The day in numbers

Time of dayTraces arriving per secondApproximate ordinary keep rateWhy it moved
3 a.m.120Close to maximumPlenty of budget for little traffic
9 a.m.3,000A few percentTraffic rose, the controller stepped down
12 noon20,000Well under one percentFlash sale, budget protected
2 p.m.6,000Around one to two percentRecovery, rates stepped up again
11 p.m.400Roughly a thirdQuiet, rates rose with spare budget
~150/s
Budget held all day
170×
Traffic swing from night to sale
100%
Errors and slow traces kept
Simple Analogy

Think of a tap that keeps a bucket at the same water level while the stream feeding it grows and shrinks. When the stream is weak the tap opens wide, and when the stream becomes a torrent the tap closes to a trickle. The level in the bucket, your storage volume, stays the same, and the important drops, the errors, are caught in a separate cup that never overflows.

i
What to Notice

Three things made the day go well: errors were protected by their own rule, metrics were computed before sampling, and the controller moved in small steps. If you can reproduce those three habits in your own system, you have captured most of the value of adaptive sampling.

19Summary and Key Takeaways

Dynamic, or adaptive, sampling is the practice of letting your tracing pipeline watch itself and adjust how many traces it keeps. It replaces a rule that follows a number with a controller that follows a goal. In OpenTelemetry you assemble it from SDK samplers, consistent probability fields, Collector processors, trace-aware routing, and remote configuration channels, or you adopt a backend or proxy that does the adjustment for you. The reward is a predictable bill and a store of traces that still answers your hardest questions. The price is more moving parts and a need to treat sampled data with statistical care. Start simple, protect errors first, record the probability on every kept trace, monitor the sampler like any other critical system, and grow the design only when a real question demands it.

Key Takeaways

  • Adaptive means goal-driven — the sampler observes live traffic, compares it with a goal such as a trace budget, and recalculates probabilities continuously.
  • Head and tail solve different problems — head sampling is cheap but blind to outcomes, while tail sampling is smart but needs memory, routing, and careful scaling.
  • OpenTelemetry gives building blocks, not one switch — samplers, trace state probability, probabilistic and tail sampling processors, load balancing, and remote configuration combine into adaptive designs.
  • Keys decide quality — use stable, low-cardinality keys, add per-key floors, and layer must-keep rules above fairness and adaptive rules.
  • Always stamp and use the probability — adjusted counts and metrics computed before sampling keep your charts truthful.
  • Protect and observe the controller — secure the control channel, redact data before buffers, monitor kept versus dropped traces, and choose a safe fallback rate.
  • Plan capacity and failure — estimate buffer memory from arrival rate, waiting period, and trace size, and design rules and dashboards that tolerate a small share of incomplete traces.
  • Grow only as needed — begin with parent-based sampling and simple policies, and add adaptive control when you can name the question it will answer.