What Is Sampling in OpenTelemetry?
A beginner-friendly guide to keeping only some of your traces: why we do it, the two main styles called head and tail sampling, the samplers you can choose, and the mistakes that trip up almost everyone at first.
Imagine you are a teacher with a class of one thousand students and you want to know how well they understand a lesson. You could give every student a long test and read all one thousand papers. That would be accurate, but it would take weeks. Or you could pick a fair group of fifty students, read their papers carefully, and learn almost as much in a single evening.
That second idea is called sampling. In OpenTelemetry, sampling means keeping only a portion of your traces, instead of every single one, so that your monitoring stays affordable and fast while still telling you the truth about your system. In this guide, we will learn what sampling is, how it works, and how to choose a sensible approach, using simple words and everyday examples.
1The Problem: Too Much Data
Before learning the tool, let us feel the problem it solves.
A quick reminder about traces
A trace is the complete story of one request as it travels through your system. It is made of many small timed steps called spans. For example, when a customer places an order, the trace may include spans for the web gateway, the order service, the payment service, and several database calls.
The numbers get big very quickly
Suppose your online store handles one thousand orders every second. Each order creates a trace with about thirty spans. That is thirty thousand spans per second, which is more than two and a half billion spans every day. Storing, sending and searching all of them costs a lot of money, uses a lot of network and memory, and makes your tools slower.
And here is the surprising part: most of those traces are boring. They are fast, successful requests that look almost the same as each other. You do not need a billion copies of “everything was fine” to understand how your system works.
Think of a security camera in a shop. Recording every second of video for years would fill huge hard disks. Most of the footage shows an empty shop. Smart systems keep only the interesting parts, such as when someone enters or when something moves at night. Sampling is how we keep the interesting parts of our telemetry and let the boring parts go.
2So, What Is Sampling?
The short answer first, and then the pieces.
Sampling is the process of deciding which traces to keep and which to throw away. The goal is to reduce the amount of data while keeping enough of it to understand your system, find problems and make good decisions.
The decision is made by a piece of logic. In the SDK inside your application, this logic is called a sampler. In the Collector, it is done by processors designed for sampling. Either way, the key idea is the same: for each trace, ask “should we keep this?”
Why not just keep everything?
Storage and Bills
Many tracing tools charge by the amount of data stored or ingested. Keeping everything can become one of your biggest monitoring costs.
Slower Searches
More data means slower queries and dashboards. Engineers waiting minutes for a search lose time during incidents.
Overhead on Your Apps
Creating, recording and sending spans uses CPU, memory and network inside your services.
Harder to Find Signals
A mountain of near-identical traces hides the few that matter. Less, well chosen, can be easier to understand.
Why not keep nothing?
Because you would be blind. The art of sampling is finding a balance: enough data to see patterns and catch problems, but not so much that you drown in cost and noise.
3Core Concepts: A Few Words You Need
Sampling has a small vocabulary. Learn these words and the rest is easy.
Sampler
The part of the SDK that decides, when a span is created, whether this trace should be kept.
Sampled Flag
A small yes or no marker that travels with the trace identity from service to service, telling everyone the decision.
Recording
Whether a span is collecting details like attributes and events inside the program. A span can be recording without being sampled.
Root Span
The first span of a trace, with no parent. It is where the first decision is usually made.
Head Sampling
Deciding at the very beginning of a trace, before anything about the request’s outcome is known.
Tail Sampling
Deciding after the trace is finished, when you already know if it was slow or failed.
The three possible decisions
When a sampler looks at a new span, it can give one of three answers.
| Decision | What It Means | Is Data Exported? |
|---|---|---|
| Drop | Do not record this span at all, and mark the trace as not sampled | No |
| Record only | Collect details locally, but the trace is not marked as sampled | Usually not sent on as part of a sampled trace |
| Record and sample | Collect details, mark the trace as sampled, and export it | Yes |
Beginners usually only need to think about two outcomes: keep or drop. The “record only” option is a more advanced tool, used for things like computing local statistics without sending the full trace.
Think of a wedding photographer. The photographer might choose to take no photo of a moment (drop), take a photo only for their own practice (record only), or take a photo that goes into the final album (record and sample). Only the last one is delivered to the family.
4Head Sampling: Deciding at the Start
The simplest and cheapest kind of sampling, done inside your application.
Head sampling means the decision is made at the very beginning of the trace, when the first span is created. The sampler looks at a few facts available at that moment, such as the trace ID, the name of the span and its starting attributes, and then says keep or drop. The decision is then carried along with the trace to every other service.
flowchart LR
A["Request arrives"] --> B["Root span is created"]
B --> C{"Sampler decides"}
C -->|Keep| D["Trace is recorded and exported"]
C -->|Drop| E["Trace is not recorded"]
D --> F["Decision travels to every service"]
E --> F
The built-in samplers
Every OpenTelemetry SDK comes with a small set of ready-made samplers. Learning these four covers most real situations.
| Sampler | What It Does | When to Use It |
|---|---|---|
| Always On | Keeps every trace | Development, testing and low-traffic services |
| Always Off | Keeps no traces | Switching tracing off without removing the setup |
| Trace ID Ratio | Keeps a fixed fraction of traces, such as one in ten, chosen using the trace ID | Cutting volume on busy services in a simple, fair way |
| Parent Based | Follows the decision made by the parent span, and uses another sampler only for new root spans | Almost every real system, so services agree with each other |
How the ratio sampler picks traces
The ratio sampler uses the trace ID as a kind of random number. The trace ID is a very large, random value. The sampler checks whether this number falls inside the chosen share. For example, if you want to keep ten percent, it keeps traces whose ID value falls in the lowest ten percent of all possible values. Because the decision depends only on the trace ID, any service using the same ratio will reach the same answer for the same trace, even without talking to each other.
Imagine a school lottery where every student has a ticket number between 1 and 100. The rule is “all tickets from 1 to 10 are chosen.” Any teacher who looks at a ticket can tell, without asking anyone, whether it was chosen. That is how a ratio sampler works with trace IDs.
Setting a sampler with simple settings
In most SDKs, you do not need to write code to choose a sampler. You use standard environment variables. One setting picks the sampler by name, such as always on, always off, trace ID ratio, or the parent-based versions of these. A second setting gives the ratio, like 0.1 for ten percent. The names are the same in nearly all languages, which makes it easy to manage them from a deployment template.
In many SDKs, the default sampler keeps every new trace. This is great for learning, but on a busy production system it can mean very high costs. Always decide on purpose what sampling setup you want before going live.
5The Parent Based Sampler Explained
The most important sampler for anyone running more than one service.
Imagine three services in a row: a gateway, an order service and a payment service. If each one made its own random decision, the gateway might keep the trace, the order service might drop it and the payment service might keep it. The result would be a broken trace with missing pieces. To avoid this, we need one decision at the start, and everyone else must follow it.
The parent-based sampler does exactly this. It checks, “Does this span have a parent?” If it does, it copies the parent’s decision. If it does not, which means it is a new trace, it asks another sampler, usually the ratio sampler, to decide.
flowchart TD
A["New span is created"] --> B{"Does it have a parent?"}
B -->|No| C["Ask the root sampler such as the ratio sampler"]
B -->|Yes| D{"Was the parent sampled?"}
D -->|Yes| E["Keep this span too"]
D -->|No| F["Drop this span too"]
C --> G["Decision is stored in the sampled flag"]
E --> G
F --> G
sequenceDiagram
participant G as API Gateway
participant O as Order Service
participant P as Payment Service
G->>G: New trace. Ratio sampler says keep
G->>O: Call with trace header and sampled flag on
O->>O: Parent was sampled so keep
O->>P: Call with trace header and sampled flag on
P->>P: Parent was sampled so keep
P-->>O: Response
O-->>G: Response
Think of a relay race where the first runner carries a flag that says either “this race is being filmed” or “this race is not being filmed.” Every runner after that simply looks at the flag. Nobody needs to argue about it. The decision is made once and shared.
Why this matters so much
Without parent-based sampling, traces become full of holes, which makes them very hard to trust. With it, a trace is either complete, from the first span to the last, or it is not there at all. This is why many guides say: in a system with more than one service, wrap your chosen sampler in a parent-based one.
Production Example: The Holes in the Trace
A team set a ten percent ratio sampler in each of their five services, without using parent-based sampling. Because each service rolled its own dice, only about one in ten thousand traces was complete across all five services. Engineers kept finding traces with missing middle steps. Switching to parent-based sampling at the services behind the gateway fixed it, and complete traces became the normal case.
6The Weakness of Head Sampling
Head sampling is simple and cheap, but it has one big blind spot.
When the head sampler decides, the request has only just started. It does not yet know if the request will fail, run slowly or do something unusual. So the choice is made blindly. If you keep ten percent at random, you also throw away ninety percent of your errors and ninety percent of your slow requests, and those are exactly the traces you most want to see.
Strengths of Head Sampling
- Very cheap, since dropped traces are never recorded at all
- Easy to set up with a few settings
- No extra servers or memory needed
- Predictable volume, since you know the share you keep
Weaknesses of Head Sampling
- Blind to errors and slowness, because the outcome is not known yet
- Rare problems may be missed entirely
- Cannot decide based on the full story of the trace
- One rate may not suit every route and every customer
Imagine a news photographer who decides at the start of a football match to take pictures only in the first and last ten minutes, without knowing when the goals will be scored. Most goals would be missed. If the photographer could wait and see the goals first, then go back and keep exactly those clips, the album would be far better. That is the idea behind tail sampling.
7Tail Sampling: Deciding at the End
The smarter, but more demanding, way to sample.
Tail sampling means waiting until a trace is finished, or almost finished, and only then deciding whether to keep it. Because the whole story is known, the rules can be much smarter. For example: “Keep every trace that has an error. Keep every trace slower than two seconds. Keep five percent of the rest.”
In OpenTelemetry, tail sampling is usually done in the Collector, using a special processor. The SDKs must send all their spans to the Collector, which holds the spans of each trace in memory for a short waiting time, and then applies the rules.
sequenceDiagram
participant A as Applications
participant C as Collector with Tail Sampling
participant B as Backend
A->>C: Send all spans of all traces
C->>C: Group spans by trace ID and hold in memory
C->>C: Wait for the decision time
C->>C: Apply rules such as errors, slowness and a small random share
C->>B: Send only the traces that passed
The kinds of rules you can write
The tail sampling processor works with a list of policies. A trace is kept if any policy says keep. The common kinds are:
Status Code
Keep traces that contain an error.
Latency
Keep traces that took longer than a chosen time.
Attribute Match
Keep traces with a certain detail, such as a specific customer tier or a debugging flag.
Probabilistic
Keep a small random share of everything else, to see normal behaviour.
Rate Limiting
Keep no more than a certain number of spans per second, protecting your budget.
Span Count
Keep traces with an unusually large or small number of spans.
Production Example: Every Failure, Few Successes
An airline booking site produces millions of traces an hour. Their tail sampling rules keep every trace with an error, every trace slower than three seconds, and one percent of the rest. Their storage bill falls by about ninety percent, yet engineers can still open the exact trace of every failed booking. Compared with simple ten percent head sampling, they see far more of the traces that matter.
The costs of tail sampling
- Memory: the Collector must hold every span of every in-progress trace until it decides. Busy systems need a lot of memory.
- Delay: data reaches the backend only after the waiting time, which may be many seconds.
- The waiting time dilemma: if you wait too short a time, late spans arrive after the decision and are lost or split off. If you wait too long, memory use and delays grow.
- Extra infrastructure: you must run, monitor and scale Collectors for this job.
- Still need to send everything: since the application cannot drop anything early, all spans must travel to the Collector first, so network and application overhead remain.
8The Hidden Requirement: Keep a Trace Together
The number one reason tail sampling setups break.
For tail sampling to make a correct decision, all the spans of one trace must arrive at the same Collector instance. If a single Collector sees only half the spans of a trace, it may think the trace is fine, when the other half contains the error. Its decision will be wrong.
The solution, when you run more than one Collector, is a two-layer design. The first layer is a set of Collectors that act as a router. They use a special load-balancing exporter that looks at the trace ID of each span and sends all spans with the same trace ID to the same second-layer Collector. The second layer does the tail sampling.
flowchart LR
A1["Service A"] --> R1["Routing Collector 1"]
A2["Service B"] --> R2["Routing Collector 2"]
A3["Service C"] --> R1
R1 -->|"Route by trace ID"| T1["Sampling Collector 1"]
R1 -->|"Route by trace ID"| T2["Sampling Collector 2"]
R2 -->|"Route by trace ID"| T1
R2 -->|"Route by trace ID"| T2
T1 --> B["Backend"]
T2 --> B
Imagine a team of examiners marking exam papers where each paper has several pages. If page one goes to one examiner and page two goes to another, nobody can give a fair mark. So a clerk at the front sorts the pages, making sure all pages of one student go to the same examiner. The routing layer is that clerk.
When a sampling Collector is added or removed, the way traces are shared among them changes, and some traces in progress may be split. Plan scaling changes carefully and expect a small amount of imperfect decisions during them.
9Head or Tail? Choosing Your Approach
Most real systems use a mix, and the choice depends on volume, budget and what you need to find.
| Question | Head Sampling | Tail Sampling |
|---|---|---|
| When is the decision made? | At the start of the trace | After the trace is complete |
| Where does it run? | In the SDK inside your application | Usually in the Collector |
| Can it keep all errors? | No, it does not know yet | Yes, with a status policy |
| Can it keep all slow traces? | No | Yes, with a latency policy |
| Cost to run | Very low | Higher: memory, extra servers and delay |
| Reduces load on applications? | Yes, dropped traces are never recorded | No, applications still record and send everything |
| Complexity | Low | Medium to high |
flowchart TD
Q["How much trace data do you have?"] --> A{"Is cost and volume a real concern?"}
A -->|No| B["Keep everything with the always on sampler"]
A -->|Yes| C{"Must you keep all errors and slow traces?"}
C -->|No| D["Use parent-based sampling with a ratio sampler"]
C -->|Yes| E{"Can you run Collectors with enough memory?"}
E -->|Yes| F["Use tail sampling in the Collector, often with light head sampling first"]
E -->|No| G["Use head sampling and capture errors through metrics and logs"]
Combining both
A very common design uses both. Head sampling in the SDK removes a large share of obviously useless traffic early, such as health checks, saving cost in the applications. Then tail sampling in the Collector looks at what remains and keeps the errors and slow traces. This way, you get savings at the start and smart choices at the end.
Production Example: Filtering Before Sampling
A team noticed that nearly half of their spans came from load balancers calling a health endpoint every second. They dropped those at the source, using a rule that looked at the request address, which is possible with head sampling or with a filter. After that, their tail sampling setup had far fewer traces to hold in memory, and the same hardware coped easily with traffic spikes.
10Sampling and Your Other Signals
Sampling traces can quietly affect metrics and logs. Here is how.
Metrics: do not count from sampled traces
Suppose you want a count of requests per minute. If you compute it by counting the traces you stored, and you only kept ten percent, your number is ten times too small. There are two safe ways to avoid this. One is to record metrics directly in the SDK, which is not affected by trace sampling. The other is to use a Collector feature that turns spans into metrics, and to place it before the sampling step, so it sees every span.
flowchart LR
S["All spans arrive at the Collector"] --> M["Span to metrics step sees every span"]
S --> T["Tail sampling decides which traces to keep"]
M --> MB["Metrics backend with accurate counts"]
T --> TB["Tracing backend with kept traces"]
Logs: the case of the missing trace
Log lines often carry a trace ID so you can jump from a log to its trace. But if that trace was sampled out, the link leads nowhere, because the trace was never stored. This is normal and expected. It is one more reason to keep errors, since an error log without its trace is frustrating. Some teams also sample logs in step with traces so that kept traces have their logs, and dropped traces do not leave a trail of orphan logs.
Counting correctly after sampling
If you keep one in ten traces, then each kept trace “stands for” ten. Some systems record the sampling probability along with the trace, so that tools can scale counts back up for estimates. If your tools do not do this for you, remember that numbers computed from sampled traces are only estimates, and write them down that way.
Think of a TV ratings company that watches one thousand homes and announces how many millions watched a show. They know each home stands for many others, so they scale the number up. If they forgot to scale it, they would report that only one thousand people watched the final of a major match. Sampled trace counts need the same care.
11Choosing a Sampling Rate
There is no single right number. Here is how to think about it.
Know Your Volume
Find out how many traces and spans you produce per second and per day, and what your tools charge or allow.
Decide What Must Never Be Lost
List the traces you always want: errors, very slow requests, payments, or requests from important customers.
Choose a Budget
Decide how much trace data you can afford to store and search comfortably.
Start Conservative
Begin with a moderate keep rate, such as ten percent for busy services, and always keep traces for low-traffic services.
Measure and Adjust
Watch how much data you keep, whether you can answer your questions, and whether rare problems are being caught. Adjust gradually.
Different rates for different things
One rate for everything is simple, but often wasteful. A checkout request is more valuable than a request for a static image. A service that gets ten requests an hour should be sampled at one hundred percent, since there is little data to start with. A service that gets ten thousand requests a second may need a very low rate. Tail sampling policies and attribute-based head sampling let you set different rates for different cases.
Any numbers you hear online, such as “keep one percent” or “keep ten percent,” are examples, not rules. The right setting depends on your traffic, your tools and your questions. Treat them as starting points and let your own measurements decide.
12Advantages, Disadvantages and Trade-offs
An honest look at what sampling gives and what it costs.
Advantages
- Lower cost: less to store, send and search
- Faster tools: smaller data means quicker queries
- Lighter applications: head sampling saves CPU and memory at the source
- Clearer picture: fewer boring traces means interesting ones stand out
- Flexible: many samplers and policies to match your needs
- Standard: the sampled flag works across languages and vendors
Disadvantages
- Missing data: some traces are gone for good, including some you wish you had
- Rare events at risk: low rates may skip rare problems entirely
- Estimates, not exact counts: numbers from sampled traces must be scaled
- Tail sampling is heavy: memory, delay and extra infrastructure
- Easy to misconfigure: broken traces and wrong rates are common mistakes
- Hard to debug a specific request: the one you need may not have been kept
Key trade-offs
| Decision | Option A | Option B |
|---|---|---|
| Keep rate | High, for more detail and higher cost | Low, for lower cost and a higher chance of missing rare cases |
| Where to decide | In the SDK, cheap and simple | In the Collector, smarter but heavier |
| Waiting time in tail sampling | Long, so late spans are included but memory and delay grow | Short, so memory is lower but late spans may be missed |
| Rules | Few simple rules, easy to understand | Many detailed rules, more precise but harder to maintain |
| Debug visibility | Keep all traces for a test group of users | Rely on random chance and risk missing the case you need |
13Security and Privacy Considerations
Sampling reduces data, but it does not make data safe by itself.
Kept Traces Still Need Cleaning
Sampling removes whole traces, not sensitive values inside the ones that remain. Still remove personal data and secrets from kept traces.
Forced Sampling
An outsider can send a request with the sampled flag switched on, trying to make you record and store far more than planned. At public edges, ignore or override incoming flags, or use rate limits.
Tail Sampling as a Target
A flood of requests with many different trace IDs can fill the Collector’s memory. Use limits on the number of traces held, and a memory limiter.
Protect the Collector Endpoint
Anyone who can send data to your Collector can influence what it holds. Use encryption and authentication.
Traces Wait in Memory
While waiting for the decision, full traces, including their details, sit in memory. Redact sensitive values before the sampling step where you can.
Retention Rules Still Apply
Even sampled data may contain personal information. Apply your retention and deletion rules to what you keep.
Do not treat sampling as a replacement for privacy controls. A common wrong thought is “we only keep one percent, so the risk is small.” One percent of a very large number is still a lot of records, and each one may expose a real person’s data.
14Monitoring, Logging and Troubleshooting
You must be able to see what your sampling is doing, or you will not trust your traces.
- Kept versus total: track how many traces or spans are created, and how many are kept. The ratio should match your plan.
- Share of complete traces: if many traces have only one or two spans, parent-based sampling may be missing in some service.
- Tail sampling health: the Collector reports metrics about traces held in memory, traces sampled, and traces dropped too early. These names start with the Collector’s name, then processor and tail sampling.
- Dropped too early: a rising count means traces are being pushed out before a decision, a sign that memory limits or waiting times are too small.
- Memory and CPU: watch the sampling Collectors closely, especially at traffic peaks.
- Routing balance: check that traces are spread fairly across the sampling Collectors.
- Error coverage: compare the error counts from metrics with the number of error traces you keep. They should be close if your policy is to keep all errors.
- Data delay: measure how long after a request the trace appears in the backend. Tail sampling adds the waiting time.
Common symptoms and likely causes
| Symptom | Likely Cause | What to Try |
|---|---|---|
| Traces have missing middle steps | Services sample independently, not following the parent | Use parent-based sampling in every service |
| Almost no traces appear | Ratio too low, or always off was set | Check the sampler settings and the ratio value |
| Bill is much higher than planned | Default always-on sampler still active | Set a sampler on purpose and verify with kept versus total counts |
| Some errors are missing | Head sampling dropped them before the error happened | Add tail sampling for errors, or lower the drop rate on critical routes |
| Tail sampling keeps wrong traces | Spans of one trace are split across Collectors | Add a routing layer that routes by trace ID |
| Collector runs out of memory | Too many traces held for too long | Lower the waiting time or the trace limit, add memory limiter and scale out |
| Request counts look too low | Counts computed from sampled traces | Compute metrics in the SDK or before the sampling step |
15Design Patterns and Anti-Patterns
Habits worth copying and traps worth avoiding.
Good design patterns
Parent Based Everywhere
Wrap your sampler in a parent-based one in every service, so decisions are shared and traces stay whole.
Cheap First, Smart Later
Drop obvious noise early at the source, then let tail sampling choose among what is left.
Always Keep the Interesting
Policies that keep all errors and slow traces ensure the most useful data survives.
Baseline Sample
Keep a small random share of everything, so you also learn what normal looks like.
Metrics Before Sampling
Count and measure using every span or in the SDK, so numbers stay accurate.
Two-Layer Collectors
A routing layer that groups by trace ID in front of the sampling layer, so tail sampling sees whole traces.
Anti-patterns
The Mistake
Setting a separate random ratio in every service without following the parent.
Why It Hurts
Each service rolls its own dice, producing traces with holes and almost no complete ones.
Better Approach
Use a parent-based sampler everywhere, with the ratio decided only at the front door.
The Mistake
Counting traffic or errors by counting stored traces.
Why It Hurts
The numbers are too small by the sampling factor, leading to wrong dashboards and wrong alerts.
Better Approach
Record real metrics from the SDK, or build metrics from spans before the sampling step.
The Mistake
Running several tail sampling Collectors with no routing by trace ID.
Why It Hurts
Each Collector sees only part of each trace, so decisions are wrong and traces are half kept.
Better Approach
Add a routing layer, or use a single sampling tier that can handle the volume.
The Mistake
Setting a very low rate on a low-traffic service.
Why It Hurts
You may keep almost nothing, so when something goes wrong there is no trace to look at.
Better Approach
Keep a high or full rate for services with little traffic, and sample heavily only where volume is large.
The Mistake
Trusting the incoming sampled flag from the public internet.
Why It Hurts
Anyone can force you to record and pay for as many traces as they like.
Better Approach
At public edges, decide the sampling yourself, and use limits on how many traces are kept per second.
16Best Practices and Common Mistakes
A practical checklist for sampling you can trust.
Best practices
- Choose on purpose. Do not leave the default sampler on production without deciding.
- Use parent-based sampling. Make sure all services follow one decision per trace.
- Always keep errors and slow requests. If you can run tail sampling, make this your first policy.
- Keep a baseline. Retain a small random share of normal traces to understand healthy behaviour.
- Sample by value. Give important routes and customers higher rates than unimportant ones.
- Protect metric accuracy. Compute counts and rates before sampling or in the SDK.
- Put sampling after filtering and before batching in the Collector. Remove noise first, choose what to keep, then pack the data.
- Size tail sampling carefully. Set the waiting time and trace limits using real traffic, and add a memory limiter.
- Measure kept versus total. Check regularly that the real keep rate matches your plan.
- Write down your policy. Record the rates, rules and reasons, so teammates know why a trace may be missing.
Common mistakes beginners make
- Believing that a ten percent rate means “we see ten percent of the problems.” Random sampling may miss rare errors entirely.
- Forgetting that sampled-out traces are gone, and then being unable to debug a specific complaint.
- Using different sampling ratios in different services without parent-based sampling.
- Confusing “recording” with “sampled.”
- Setting the tail sampling waiting time too short, so late spans are lost.
- Forgetting that tail sampling needs all spans of a trace in one place.
- Assuming sampling removes privacy risk.
17Real-World and Industry Examples
How sampling shows up in tools and platforms you may already know.
Google Dapper
Google’s early tracing system, described in a well-known research paper, kept only a tiny fraction of requests on its very busiest services. It showed that even a very low sampling rate can reveal useful patterns when traffic is large, and it helped shape how the industry thinks about tracing cost.
Jaeger
Jaeger, which began at Uber and is now a CNCF project, supports remote sampling, where the sampling rate for each service is set centrally and fetched by the applications. This lets operators change rates without redeploying services, and it inspired a sampler type in the OpenTelemetry SDKs.
AWS X-Ray
AWS X-Ray lets you define sampling rules with a small guaranteed number of traces each second and a fixed percentage of the rest. This gives every route some visibility, while keeping the total volume under control. Applications built with the AWS Distro for OpenTelemetry can use X-Ray with these rules.
Honeycomb Refinery
Honeycomb offers a sampling proxy called Refinery that makes tail-based decisions on traces before they are stored. Teams place it in front of storage to keep errors and slow requests while cutting the volume of ordinary traces, which shows how widely tail sampling is used in practice.
The OpenTelemetry Collector and Grafana Tempo Users
Many teams that send traces to open-source storage such as Grafana Tempo run the Collector’s tail sampling processor, or an agent built on Collector components, in front of it. They keep the traces that matter and avoid paying to store every healthy request.
A typical journey for a growing company
Keep Everything at First
With low traffic, use always on and learn what your traces look like.
Add Parent-Based Ratio Sampling
As volume and costs grow, add a simple ratio at the front door and follow it everywhere.
Remove Obvious Noise
Drop health checks and other low-value requests at the source.
Introduce Tail Sampling
Keep all errors and slow traces with Collector policies, with a routing layer when you scale out.
Govern and Review
Document the policy, monitor kept versus total, and review rates when traffic or goals change.
18Frequently Asked Questions
Quick answers to questions beginners ask most.
19Summary and Key Takeaways
If you remember only a few things, remember these.
Key Takeaways
- Sampling keeps some traces to save cost and noise. The goal is enough data to understand your system, not every single trace.
- Head sampling is cheap but blind. It decides at the start in the SDK, before it knows whether the request will fail or be slow.
- Tail sampling is smart but heavier. It decides at the end in the Collector, so it can keep all errors and slow traces, at the cost of memory, delay and extra infrastructure.
- Always use parent-based sampling. One decision at the front door, shared through the sampled flag, keeps traces whole across services.
- Tail sampling needs whole traces in one place. Use a routing layer that sends all spans of a trace to the same Collector.
- Protect your metrics. Record them in the SDK or compute them before sampling, and treat counts from sampled traces as estimates.
- Choose, measure and secure. Pick rates on purpose, watch kept versus total, guard against forced sampling, and remember that sampling does not remove sensitive data from the traces you keep.