What Are Trace Flags in OpenTelemetry?

What Are Trace Flags in OpenTelemetry?

A friendly, ground-up guide to the tiny set of on and off switches that travel with every trace: what each switch means, how a single decision at the front door reaches every service, where the switches are stored, and how to keep them honest and safe.

Imagine a relay race with a long chain of runners. Before the race starts, an official pins a small coloured badge on the baton. A green badge means “this race is being filmed, so please run in front of the cameras.” A plain badge means “no filming today.” Every runner who receives the baton looks at the badge and behaves accordingly. Nobody phones the official to ask. The badge itself carries the message from the first runner to the last.

In OpenTelemetry, a request that travels through many services carries a similar badge. That badge is made of trace flags: a very small group of on and off switches that ride along with the trace identity. They answer simple but important questions, above all, “is this trace being kept?” In this guide, we will learn what trace flags are, what each switch means, where they are stored, how they travel, and how to use and protect them, using simple words and everyday examples.

8 bits
Size of the trace flags: one byte, eight switches
1
Switch everyone knows: the sampled flag, in the lowest bit
2 hex
Characters at the end of the standard traceparent header that hold the flags

1The Problem: How Do Many Services Agree Without Talking?

Before learning the tool, let us feel the problem it solves.

A quick reminder about traces and sampling

A trace is the complete story of one request as it travels through your system, made of timed steps called spans. In a large system, recording every trace is expensive, so most companies keep only a share of them. Choosing which traces to keep is called sampling.

The agreement problem

Suppose a customer’s request passes through five services: a gateway, an order service, a payment service, an inventory service and a notification service. If the gateway decides to keep this trace, the other four must also record their parts. Otherwise the trace will have holes, and holes make traces hard to trust. But the five services may run in different languages, on different machines, in different countries, owned by different teams. They cannot all pause to hold a meeting about each request.

The elegant solution is to make the decision once, at the start, and write it into a tiny message that travels along with the request. Every later service reads the message, learns the decision, and follows it. That tiny message is stored in the trace flags.

Everyday Analogy

Think of a school trip permission slip stapled to every child’s bag. The slip carries a few tick boxes: “photos allowed,” “medical form on file.” Every teacher, guide and driver along the way can read the ticks. Nobody needs to call the school office for each child. The tick boxes are the trace flags.

sequenceDiagram
    participant G as API Gateway
    participant O as Order Service
    participant P as Payment Service
    participant N as Notification Service
    G->>G: Decide to keep this trace and set the sampled flag
    G->>O: Request with trace identity and flags
    O->>O: Read flags and record the span
    O->>P: Request with the same flags
    P->>P: Read flags and record the span
    P->>N: Request with the same flags
    N->>N: Read flags and record the span
    
Figure 1: One decision at the front door is carried to every service in the flags

2So, What Are Trace Flags?

The short answer first, and then the pieces.

Trace flags are a small set of on and off switches stored as part of a span’s identity, called the span context. They are one byte in size, which means eight switches. Each switch is a single bit that is either zero or one. Trace flags describe facts about the whole trace, and they travel from service to service with the trace ID and span ID.

Trace flags are the tick boxes on the trace’s permission slip.

Where trace flags fit in the span context

A span context is the small, unchangeable identity card of a span. It holds five items. We introduce each one briefly, so that you can see where the flags sit.

Item 1

Trace ID

The shared number of the whole journey. Every span in the trace has the same one.

Item 2

Span ID

The number of this one step inside the trace.

Item 3

Trace Flags

The group of on and off switches. This is our topic today.

Item 4

Trace State

An optional list of vendor notes in key and value form, separate from the flags.

Item 5

Is Remote

A local marker saying whether this context arrived from another program.

What trace flags are not

  • They are not span attributes. Attributes describe one span in detail. Flags describe the trace as a whole, and they are tiny.
  • They are not the trace state. The trace state holds free-form vendor notes. Flags hold fixed, standard switches.
  • They are not baggage. Baggage holds your own key and value notes. Flags hold only standard switches.
  • They are not a command. As we will see, the main flag is more like a strong hint than an order.
  • They are not about success or failure. That is the job of the span status.

3Anatomy: One Byte, Eight Switches

Reading trace flags is easy once you know how to read a single byte.

A quick lesson on bits and hex

A bit is the smallest piece of computer data: it is either 0 or 1, like a light switch that is off or on. A byte is a group of eight bits. Because eight switches in a row are awkward to write down, people write a byte using two hexadecimal characters, which is a counting system that uses the digits 0 to 9 and the letters a to f. So the byte with all switches off is written “00”, and the byte with only the lowest switch on is written “01”.

flowchart LR
    A["Trace flags byte"] --> B["Bit 7: reserved"]
    A --> C["Bit 6: reserved"]
    A --> D["Bit 5: reserved"]
    A --> E["Bit 4: reserved"]
    A --> F["Bit 3: reserved"]
    A --> G["Bit 2: reserved"]
    A --> H["Bit 1: random trace ID flag in newer versions"]
    A --> I["Bit 0: sampled flag"]
    
Figure 2: The eight switches in the trace flags byte, counted from the lowest bit

What each position means

Bit PositionHex Value When OnNameStatus
Bit 0, the lowest01SampledStandard and widely used
Bit 102Random trace IDDefined in newer revisions of the W3C standard, with support still maturing
Bits 2 to 704, 08, 10, 20, 40, 80ReservedNot assigned. They exist for future needs

Reading some real values

Flags as WrittenSwitches That Are OnPlain Meaning
00NoneThe trace is not sampled
01SampledThe trace is sampled
02Random trace ID onlyNot sampled, and the trace ID was generated randomly
03Sampled and random trace IDSampled, and the trace ID was generated randomly

Where you see them

In the standard web header called traceparent, there are four parts joined by dashes: a version, the trace ID, the parent span ID and the flags. The flags are the last two characters. A full header might end in “01”, which tells the receiver that the sampled switch is on.

Part of the HeaderExampleWhat It Tells You
Version00The format version
Trace ID0af7651916cd43dd8448eb211c80319cThe shared journey number, 32 characters
Parent Span IDb7ad6b7169203331The caller’s span, 16 characters
Trace Flags01The sampled switch is on
Everyday Analogy

Think of a row of eight light switches by a door. Only the first switch has a label, “filming on.” The second switch has a newer label that not every building understands yet. The other six have blank labels, saved for later. When someone describes the row as “01”, they mean “only the first switch is up.”

4The Sampled Flag in Depth

The one flag every OpenTelemetry user meets, and the reason the others are rarely discussed.

The sampled flag says whether the trace is being kept. When it is on, the caller recorded its part of the trace, and downstream services are encouraged to record theirs as well. When it is off, the caller did not record, and downstream services should normally not record either.

A hint, not a command

The standard describes the sampled flag carefully. It says that the flag indicates that the caller may have recorded trace data, and that when the flag is off, the caller did not record. It is a statement of what the caller did, which the receiver may use as strong guidance. The receiver is still free to make its own decision, within the rules of its own sampler.

Flag ReceivedWhat the Caller Is SayingWhat a Typical Receiver Does
Sampled on“I recorded my part of this trace”With parent-based sampling, record too, so the trace stays whole
Sampled off“I did not record my part”With parent-based sampling, do not record either
No header at all“I did not pass a trace to you”Start a new trace and make a fresh decision

How the flag is first created

At the start of a new trace, there is no parent. The sampler, which is the component in the SDK that decides whether to keep a span, makes the first decision. If it says “record and sample,” the sampled switch is turned on in the new span’s flags. If it says “drop,” the switch is left off. Every child span and every call made onward inherits that value, unless a sampler somewhere along the chain deliberately chooses otherwise.

i
Tip

Most SDKs offer a simple helper on the span context, often called “is sampled,” that reads this one switch for you. You rarely need to work with the raw byte yourself.

Why the flag matters even when a trace is dropped

When a trace is not sampled, the span context is still created and still passed on. The next service needs to learn that the decision was “not sampled.” If the context were not passed, the next service would think it was the start of a brand new journey, make its own decision, and perhaps keep a trace that the front door had dropped. That would produce a partial trace, with a root that appears in the middle of the story. So the rule is simple: always pass the context on, even when the flag is off.

Production Example: The Orphan Middle

A team’s gateway dropped ninety percent of traces by sampling. But a proxy between the gateway and the order service stripped the trace header whenever the sampled flag was off, to “save bandwidth”. The order service saw no header, started its own new trace, and kept ten percent of those. The result was a stream of traces that began halfway through the story, and a puzzled team. Fixing the proxy to pass the header unchanged restored whole traces.

5Sampled versus Recording: Two Different Ideas

The most common confusion about trace flags, cleared up.

The words “recording” and “sampled” sound alike, but they mean different things. Understanding the difference makes many odd behaviours make sense.

Local Fact

Recording

A property of one span inside one program. A recording span collects details such as attributes and events. It is not stored in the trace flags.

Shared Fact

Sampled

A property of the trace as a whole, stored in the trace flags and passed to every service. It says whether the trace will be kept and exported.

Recording?Sampled Flag?Sampler DecisionWhat It Means in Practice
NoOffDropThe span is a lightweight shell. Nothing is recorded or exported.
YesOffRecord onlyThe program collects details for its own use, such as computing metrics from spans, but the trace is not promised to anyone and is normally not exported as a kept trace.
YesOnRecord and sampleThe span is collected, marked as sampled, and exported.
NoOnUnusualCan happen when a program has no SDK and simply passes on a sampled parent. It records nothing, but keeps the flag intact for others.
flowchart TD
    A["Sampler is asked about a new span"] --> B{"Which decision?"}
    B -->|Drop| C["Not recording. Flag stays off."]
    B -->|Record only| D["Recording. Flag stays off."]
    B -->|Record and sample| E["Recording. Flag is turned on."]
    C --> F["Context with flag off passes to next service"]
    D --> F
    E --> G["Context with flag on passes to next service"]
    
Figure 3: How the three sampler decisions set recording and the sampled flag
Everyday Analogy

Think of a student taking notes in class. Taking notes is “recording.” Handing the notes in to the teacher is “sampled.” A student can take notes without handing them in. A person with no pen and paper at all can still pass along the message “the teacher wants everyone’s notes today,” which is like a program with no SDK passing on a sampled flag without recording anything.

!
Watch Out

Do not read the trace flags to decide whether your own span is recording. Use the span’s own “is recording” check. The flags describe the trace, and recording describes one span in your program.

6The Random Flag: A Newer Switch

A second switch that helps fairness and counting in advanced sampling.

Many sampling methods use the trace ID as a fair lottery number. For this to be fair, the trace ID must be truly random. If some system builds trace IDs from a counter or from a pattern, such as starting with the date, then a sampler that uses part of the ID as a random number could pick traces unevenly: all the traces from one morning might be kept, or none.

To address this, newer revisions of the W3C trace context standard define a second flag, often called the random trace ID flag. When it is on, the creator of the trace promises that the trace ID, or at least the part of it used for sampling, was generated with proper randomness. Receivers and tools can then trust it for sampling decisions and for estimating totals.

flowchart TD
    A["Trace ID arrives with flags"] --> B{"Is the random flag on?"}
    B -->|Yes| C["Safe to use the trace ID as a lottery number for consistent sampling"]
    B -->|No| D["Do not assume randomness. Use another method or generate a fresh ID"]
    
Figure 4: The random flag tells receivers whether the trace ID can be trusted as a fair lottery number
Everyday Analogy

Think of raffle tickets. If every ticket number was drawn from a well-shuffled drum, picking all numbers ending in 7 gives a fair share. But if the tickets were printed in order and handed out by street, then “all numbers ending in 7” might all go to one street. A note on the book saying “numbers were drawn from a shuffled drum” is the random flag.

i
Tip

This area is newer than the sampled flag. Support differs between languages, Collectors and backends, and the exact rules have been evolving. Most teams today only rely on the sampled flag. Check the current standard and your tools before depending on the random flag.

7Reserved Bits and Forward Compatibility

Why six switches have no labels, and what to do with them.

The remaining bits in the trace flags byte are reserved. This means the standard keeps them for future uses that have not been defined yet. A good standard plans for the future, and the reserved bits are the room left for it.

The rules for reserved bits

  • Do not give them your own meaning. If every vendor invented its own use for the spare switches, two systems could read the same bit in different ways, and trace data would be misread.
  • Set them to zero when you create flags. A new trace should begin with the reserved bits off.
  • Ignore bits you do not understand. A program that reads a flag byte with an unfamiliar bit turned on should still read the parts it knows, and not reject the whole header.
  • Be careful when passing on. Libraries differ in whether they keep or clear unknown bits. Check the behaviour of your propagator, particularly if you rely on a newer flag that your older components do not know.
Everyday Analogy

Think of a form with some boxes marked “reserved for office use.” Applicants should leave those boxes blank, and clerks who do not know what the boxes are for should not scribble in them. When the office later decides how to use them, old forms still work.

Why forward compatibility matters

Because the flags byte is part of a standard used by thousands of products, a new switch can only be added if old software keeps working when it sees the new switch turned on. By ignoring unknown bits, old and new software can share the same traces, and the standard can grow slowly, without a day when everything must change at once.

8Where Trace Flags Live

The same switches appear in several places along a telemetry journey.

In Memory

The Span Context

Inside your program, the flags are a field of the span context, readable through helper methods such as an “is sampled” check.

On the Wire

The Trace Parent Header

Between services, the flags are the last two hexadecimal characters of the standard trace parent header.

In Messages

Message Headers

For queues and event streams, the same header text is stored inside the message’s own headers or properties.

In Export

Exported Spans

When spans are sent in the standard OpenTelemetry protocol, each span carries a flags field, which also holds extra bits saying whether the parent was remote.

In Logs

Log Records

A log record can carry the trace flags of the span that was active when it was written, along with the trace and span IDs.

In Tools

Backends and Viewers

Tracing backends may show whether a span was sampled, and some tools use the flag when linking logs, metrics and traces.

The exported span flags

In the standard protocol used to send telemetry, called OTLP, each span has a field for flags. The lowest eight bits hold the same trace flags we have been discussing. Two further bits record whether the span’s parent was remote, meaning it came from another program, and whether that information is known at all. This extra detail helps tools tell the difference between a span whose parent is missing because it was lost and a span whose parent is simply in another service. The exact fields can differ between protocol versions, so check the version you use.

Flags on log records

The log data model includes a trace flags field next to the trace ID and span ID. This lets a logging pipeline see whether the trace that a log line belongs to was sampled. A pipeline might use this to keep log lines only for sampled traces, or to keep all error logs regardless, depending on policy.

flowchart LR
    A["Span context in memory"] --> B["traceparent header on outgoing requests"]
    A --> C["Message headers for queues"]
    A --> D["Exported span flags in OTLP"]
    A --> E["Log record trace flags"]
    B --> F["Next service reads the flags"]
    C --> F
    D --> G["Collector and backend"]
    E --> G
    
Figure 5: The same flags appear in memory, on the wire and in exported data

9Internal Working: How the Flags Are Set, Inherited and Passed On

Let us follow the flags through the life of a request.

1

A Request Arrives With No Trace

The first service sees no trace header. It creates a root span, generates a trace ID and a span ID, and asks its sampler for a decision.

2

The Sampler Sets the First Flag

If the sampler says “record and sample,” the sampled switch is turned on in the new span context. Otherwise it is left off.

3

Child Spans Inherit

Any child span created inside the same program copies the parent’s flags. A well-behaved parent-based sampler follows the parent’s sampled value.

4

The Propagator Writes the Header

When making an outgoing call, a component called a propagator writes the span context, including the flags, into the request header.

5

The Next Service Reads the Header

The receiving service reads the header, builds a remote span context, and uses it as the parent of its new server span.

6

The Sampler Consults the Parent

With a parent-based sampler, the new span follows the parent’s sampled flag, and the same flags continue in its own outgoing calls.

sequenceDiagram
    participant U as User
    participant A as Service A with sampler
    participant B as Service B parent based
    participant C as Service C parent based
    U->>A: Request with no trace header
    A->>A: New trace. Sampler rolls. Flags become 01
    A->>B: traceparent ends with 01
    B->>B: Parent sampled so keep. Flags stay 01
    B->>C: traceparent ends with 01
    C->>C: Parent sampled so keep. Flags stay 01
    U->>A: Another request with no trace header
    A->>A: New trace. Sampler rolls. Flags become 00
    A->>B: traceparent ends with 00
    B->>B: Parent not sampled so drop. Flags stay 00
    B->>C: traceparent ends with 00
    C->>C: Parent not sampled so drop. Flags stay 00
    
Figure 6: Two requests, two decisions, and how the flags carry each one through three services

Immutability: changing a flag means making a new context

A span context cannot be edited after it is created. If something needs to change a flag, for example a sampler that wants to override the parent’s decision, it creates a new span context with the new value. This keeps data safe when many parts of a program read the same context at once, and avoids surprising changes in the middle of a request.

What happens in a program with no SDK

If only the API is present and no SDK is installed, the API still reads the incoming context and passes it on unchanged when calling other services. The flags travel through that program untouched, even though it records nothing. This is a clever safety feature: an uninstrumented hop in the middle of a journey does not break the trace or change its sampling decision.

10Flags in Other Propagation Formats

The W3C format is the default, but older and cloud-specific formats carry the same idea in their own way.

Before the W3C standard, various tools invented their own headers. Many companies still run systems that speak these formats. OpenTelemetry’s propagators, the components that read and write headers, can translate between them and the common internal span context.

FormatHow the Sampling Decision AppearsSpecial Extras
W3C Trace ContextThe flags byte, with the lowest bit as sampledNewer revisions add a random trace ID flag
B3, from ZipkinA sampled value of 1 or 0, in a single header or in separate headersA debug value that means “force this trace to be kept”
JaegerA flags field inside the combined trace header, with the lowest bit as sampledA debug bit, and a separate debug identifier header, used to force tracing
AWS X-RayA sampled value of 1 or 0 in the trace headerA value that means “sampling decision is requested from the receiver”
Google Cloud trace headerAn options value at the end of the header, where 1 means tracedTied to Google’s own trace identity format
flowchart LR
    A["Incoming B3 header with sampled 1"] --> P["Propagator reads it"]
    B["Incoming W3C header with flags 01"] --> P
    C["Incoming Jaeger header with sampled bit"] --> P
    P --> S["Internal span context with sampled flag on"]
    S --> O1["Outgoing W3C header with flags 01"]
    S --> O2["Outgoing B3 header with sampled 1"]
    
Figure 7: Propagators translate between header formats using the sampled flag as the shared idea

The “debug” idea and why it gets lost

Some older formats have a special debug value, meaning “keep this trace no matter what the sampler would say.” Engineers use it to force a trace of a specific request while investigating a problem. The W3C standard has no debug flag. When a debug request is translated into the W3C format, the information that it was a forced trace is reduced to the plain sampled flag. Downstream services that follow the W3C format will see “sampled,” but they will not know it was forced. This can matter if a downstream sampler would override the parent’s decision.

i
Tip

When you must support several formats, configure the composite propagator with all the formats you need, and list your preferred one first. During a migration, run both old and new formats for a while, and watch the traces to make sure the sampling decision survives each hop.

Production Example: The Lost Debug Request

A support engineer used a debug header to force a trace of one customer’s failing request. The edge service honoured it, but the trace was cut off after the second service, because a newer service only understood the W3C format and dropped the older debug headers. Adding the older format to that service’s propagator list allowed the forced trace to continue to the end.

11Trace Flags, Trace State and Baggage: Three Carriers

Three different ways to carry information with a request. Each has its own purpose.

FeatureTrace FlagsTrace StateBaggage
PurposeStandard switches about the traceVendor notes that travel with the trace identityYour own notes for downstream services
SizeOne byteSmall list, limited in sizeCan grow, so keep it small
Who defines the content?The standardVendors and tools, within the standard’s rulesYou
Part of the span context?YesYesNo, it travels separately
Typical exampleSampled onA note about how a trace was sampledA customer tier or an experiment name
Everyday pictureTick boxes on a permission slipStamps from different officesA sticky note on the parcel

How they cooperate in advanced sampling

Some newer sampling designs use the trace state to record information about the sampling probability, such as a threshold value, and use the trace flags to indicate whether the trace ID is random. Together they allow later services to know both whether a trace was sampled and how likely it was to be sampled, so that counts can be scaled back up. The flags give the yes-or-no answer, and the state gives extra detail.

!
Watch Out

Do not try to use trace flags, or the reserved bits, as a place for your own information. Use baggage for your own notes, and attributes for details of a single span. Flags are a standard, shared language, and changing their meaning breaks it for everyone.

12Flags and Sampling Strategies

How the flag fits with head sampling, parent-based sampling and tail sampling.

Head sampling and the flag

In head sampling, the decision is made at the start of the trace by the sampler in the SDK. The flag is the vehicle that carries the decision. It is the core of how head sampling stays consistent across services.

Parent-based sampling and the flag

The parent-based sampler reads the incoming flag and chooses what to do for the new span. It has separate rules for whether the parent was sampled or not, and whether the parent was local or remote. This means you can control how much you trust incoming flags: follow them fully inside your own network, and treat them as hints at a public edge.

Tail sampling and the flag

Tail sampling is different. In tail sampling, the decision is made later in the Collector, after the trace is complete. The SDKs usually record and send everything, so they behave as if the sampled flag were on. The real decision is made in the Collector, which looks at the whole trace. In this design, the flag in the data may not reflect the final decision, since the decision came after. Do not use the flag on a stored span to find out whether a trace “was sampled by tail sampling”. By definition, any trace in storage was kept.

flowchart TD
    A["Application SDK"] --> B{"Which strategy?"}
    B -->|Head sampling| C["Sampler decides at start and sets the flag"]
    B -->|Tail sampling| D["SDK keeps everything and sends it, flag usually on"]
    C --> E["Dropped traces never leave the application"]
    C --> F["Kept traces go to the Collector"]
    D --> G["Collector holds each trace and decides at the end"]
    F --> H["Backend stores kept traces"]
    G --> H
    
Figure 8: The flag carries the decision in head sampling but not in tail sampling

The arithmetic across both layers

If you use both head sampling and tail sampling, remember that the head decision comes first. A trace that was dropped at the start, with the flag off, is never sent to the Collector, so the Collector cannot rescue it, even if it later turns out to contain an error. If you want the Collector to keep every error, the head sampler must not drop that trace before the error happens.

Everyday Analogy

Think of a photo booth at a fair that has a rule: “only take photos of people wearing a blue badge.” A manager later reviews all the photos to keep the best ones. The manager can only choose among photos that were taken. A person without a badge was never photographed, so the manager never sees them, however photogenic they were.

13Flags, Logs, Metrics and Exemplars

The flag is a small bridge between traces and the other signals.

Logs

When a log record is written while a span is active, it can carry the trace ID, the span ID and the trace flags. The flags tell a logging pipeline whether the linked trace was kept. This is useful in several ways.

  • Link checking: a tool can show a “view trace” button only for logs whose trace was sampled, since the trace for other logs does not exist.
  • Cost control: a pipeline can keep the logs of sampled traces in full, and keep fewer of the rest, matching the trace policy.
  • Error protection: a pipeline can keep all error logs regardless of the flag, so that important evidence is not lost.
flowchart TD
    L["Log record with trace ID and flags"] --> Q{"Is the sampled flag on?"}
    Q -->|Yes| K["Keep and link to the stored trace"]
    Q -->|No| E{"Is it an error or warning?"}
    E -->|Yes| K2["Keep, but note that no trace exists"]
    E -->|No| D["Drop or keep at a low rate"]
    
Figure 9: A logging policy that uses the flag to match the trace sampling decision

Metrics and exemplars

Metrics recorded through the metrics API do not depend on the sampled flag, so counts stay accurate. Exemplars are different. An exemplar is an example trace ID attached to a metric measurement, so that you can jump from a graph spike to a real trace. By default, SDKs usually attach exemplars only from spans whose flag says “sampled,” because linking to a trace that was never stored would lead to nothing. So the sampled flag also decides which metric points can carry a useful link.

Production Example: Graph to Trace in One Click

An engineer sees a latency spike on a chart. A few of the points carry exemplars, because the traces behind them were sampled. A click opens one such trace, where a database lock stands out. The points without exemplars come from traces that were not sampled, so there was nothing to open. The team then raises the sampling rate for the checkout route, so that more points on its charts can lead to traces.

14Data Flow and Lifecycle: A Flag From Birth to Dashboard

Follow one flag from the moment it is created to the moment an engineer sees its effect.

1

Birth at the Front Door

A root span is created and the sampler turns the sampled switch on or leaves it off.

2

Inheritance Inside the Program

Child spans copy the flags from their parent as they are created.

3

Travel Across the Network

The propagator writes the flags into outgoing request or message headers.

4

Interpretation by the Next Service

The next service reads the flags and its sampler decides, usually following the parent.

5

Export With the Span

Sampled spans are exported with their flags, together with extra details about whether the parent was remote.

6

Use by Logs and Metrics

Log records and exemplars use the flag to decide how to link or what to keep.

7

Display in the Backend

The tracing tool stores the spans, and engineers use the traces, which exist because the flag said “keep.”

15Trust at the Edge: Validating Incoming Flags

Anything in a request header was written by someone. At the public edge, that someone may not be friendly.

Inside your own network, trusting the incoming flags is usually fine. At the public edge, where requests come from the open internet, the trace header may have been written by a stranger. Strangers can write anything, including flags you did not expect.

Three kinds of problems

Abuse

Forced Recording

A caller sets the sampled flag on every request, trying to make you record and store far more than planned, raising your costs.

Malformed

Broken Headers

A caller sends a header with invalid characters, a wrong length, or a version your software does not know. Software must handle these safely.

Unexpected Bits

Unknown Flags

A caller sets reserved bits on. Software that does not understand them must ignore them and not crash or misbehave.

flowchart TD
    A["Request arrives at public edge"] --> B{"Is the traceparent header valid?"}
    B -->|No| C["Ignore it and start a new trace"]
    B -->|Yes| D{"Do we trust this caller?"}
    D -->|Yes| E["Follow the incoming flags"]
    D -->|No| F["Treat the sampled flag as a hint and apply our own policy"]
    F --> G["Optionally start a new trace and link to the caller"]
    
Figure 10: A safe way to handle incoming trace headers at a public edge

The practical controls

  • Validate the format. The standard requires specific lengths and lowercase hexadecimal characters. Software should ignore headers that do not follow the rules, and begin a new trace instead.
  • Use the remote-parent rules of the sampler. At a public edge, configure what happens when the remote parent is sampled, so a stranger’s “keep” is checked against a ratio or a rate limit rather than obeyed without question.
  • Rate limit recording. Put a cap on the number of traces recorded per second at the edge, no matter what the flags say.
  • Consider fresh traces with links. Start your own trace for requests from outsiders, and record the caller’s trace as a link, so that cross-company debugging is still possible.

Production Example: The Flag Flood

A public API’s tracing bill suddenly tripled. Investigation showed that a partner’s library always set the sampled flag on every request, and the gateway followed it blindly. Changing the gateway’s rule for remote sampled parents from “always follow” to “apply a ratio” returned the bill to normal, with no change on the partner’s side.

16Advantages, Disadvantages and Trade-offs

An honest look at what trace flags give and what they cost.

Advantages

  • Tiny: one byte adds almost nothing to each request
  • Standard: understood by many languages, vendors and tools
  • No meetings needed: one decision reaches every service on its own
  • Keeps traces whole: everyone follows the same keep or drop choice
  • Works through uninstrumented hops: the flag passes through unchanged
  • Room to grow: reserved bits allow future switches without breaking old software

Disadvantages

  • Only a hint: receivers may follow or override it, so behaviour varies
  • Easy to lose: a proxy or library that drops or rewrites headers breaks the chain
  • Blind to outcome: set at the start, so it cannot depend on errors or slowness
  • Untrusted at the edge: outsiders can set it to abuse your system
  • Format mixing: translating between formats can lose details like debug
  • Newer flags are still maturing: support for the random flag differs between tools

Key trade-offs

DecisionOption AOption B
Trust incoming flagsFollow them fully, for whole end-to-end tracesTreat them as hints, for cost safety at public edges
Header formatsOnly W3C, simple and consistentSeveral formats, to bridge old systems, with more to maintain
Use of newer flagsAdopt early for better sampling mathWait for broad support to avoid mismatched behaviour
Log policyTie logs to the sampled flag, saving costKeep all logs, losing the saving but keeping all evidence
Forced tracesSupport a debug-style override for investigationsNo override, safer but harder to investigate one request

17Security and Privacy Considerations

The flags themselves hold no personal data, but how you treat them still matters.

Not a Secret

Flags Are Visible

They travel in plain headers. Anyone who can see the request can read them. Never use them as secrets or tokens.

Not Identity

No Proof of Who You Are

A request with the sampled flag on has not proved anything about the caller. Do not grant special treatment because of it.

Cost Attack

Forced Sampling

Callers who force recording can raise your storage and network costs. Add limits at public edges.

Overrides

Guard Debug Switches

A header that forces tracing on is useful for engineers, but outsiders must not be able to use it. Accept it only from trusted callers.

Third Parties

Headers Reach Others

When you call outside services, your trace headers go with the request. This is usually harmless, but you may prefer not to send them to untrusted parties.

Kept Data

Sampled Traces Still Need Cleaning

The flag decides what is kept, not what is inside. Redact personal data and secrets in the traces that are kept.

!
Watch Out

Never let the flags drive any security decision, such as who may see data or which requests are allowed. They are a convenience for telemetry only, and any caller can set them to any valid value.

18Monitoring, Logging and Troubleshooting

When flags go wrong, the symptoms are visible if you look for them.

  • Share of requests arriving with the flag on: compare with the share you expect. A jump may mean a partner is forcing recording.
  • Share of spans recorded versus flag on: if many requests arrive with the flag on but few spans are exported, exporters or processors may be failing.
  • Traces with only one or two spans: suggest that flags or headers are lost between services.
  • Roots in the middle of the system: a trace whose first span is deep inside the system suggests a hop that drops the header.
  • Invalid header counts: count malformed or unreadable headers at your gateways.
  • Per-service keep rates: each service should keep about the same share. One that differs may not follow the parent.
  • Log link success: measure how often a log’s trace link leads to a stored trace.
  • Format mismatches: during migrations, watch for traces that break at the boundary between systems that use different formats.

Common symptoms and likely causes

SymptomLikely CauseWhat to Try
Traces have missing middle stepsA service makes its own decision and ignores the incoming flagUse a parent-based sampler in every service
Traces start in the middleA proxy or library drops the header when the flag is offMake every hop pass the header unchanged
Tracing bill suddenly risesCallers force the flag on, and the edge follows blindlyApply a ratio or rate limit for remote sampled parents at the edge
Debug override stops working partwayA service understands only W3C and drops older debug headersAdd the older format to the propagator list
Logs show trace links that lead nowhereThe trace was not sampled, so none is storedCheck the flag on the log, and consider keeping more traces for key routes
Flag seems to show on although traces are missingSpans were created but exporters or Collector steps dropped themCheck exporters, queues and Collector filters
Header ignored by one serviceHeader is malformed, such as uppercase characters or wrong lengthCheck the format rules, and fix whichever component writes the header

19Design Patterns and Anti-Patterns

Habits worth copying and traps worth avoiding.

Good design patterns

Pattern

Decide Once, Carry Everywhere

Let one front door make the keep or drop decision, and let all other services follow the flag.

Pattern

Always Pass the Context

Pass trace headers on every hop, even when the flag is off, so the decision is never lost.

Pattern

Validate at the Edge

Check incoming headers for format and trust, and apply your own policy for outsiders.

Pattern

Let Libraries Write Headers

Use propagators and instrumentation libraries, instead of building header text by hand.

Pattern

Flag-Aware Logging

Use the flag on log records to align log keeping with trace sampling, and keep all errors.

Pattern

End-to-End Propagation Test

Run a simple test through all key services that checks the flag stays the same from first to last.

Anti-patterns

ANTI-PATTERN 01Avoid
The Mistake

Dropping or stripping trace headers when the sampled flag is off.

Why It Hurts

The next service believes a new journey has started and makes its own decision, producing traces with roots in the middle.

Better Approach

Always pass the header on unchanged, whatever the flag says.

ANTI-PATTERN 02Avoid
The Mistake

Hard-coding the flags value, such as always writing “01” in a hand-built header.

Why It Hurts

Every trace appears sampled, whatever the real decision, and downstream services record data that should have been dropped.

Better Approach

Use the standard propagator to write the real flags from the real span context.

ANTI-PATTERN 03Avoid
The Mistake

Using the reserved bits or the trace flags for your own purposes.

Why It Hurts

Other systems may read the same bits in a different way, and a future standard may assign them a meaning that clashes with yours.

Better Approach

Use baggage for your own notes and span attributes for details.

ANTI-PATTERN 04Avoid
The Mistake

Trusting the sampled flag from the public internet without limits.

Why It Hurts

Anyone can force you to record, store and pay for as many traces as they like.

Better Approach

Apply a ratio or rate limit for remote sampled parents at the edge, or start fresh traces and link.

ANTI-PATTERN 05Avoid
The Mistake

Reading the flags to decide whether a span is recording.

Why It Hurts

Recording and sampled are different. The flag may be on for a non-recording pass-through span, or off for a record-only span.

Better Approach

Use the span’s own “is recording” check for local decisions.

ANTI-PATTERN 06Avoid
The Mistake

Using the sampled flag as a security signal, such as “sampled requests are from trusted users”.

Why It Hurts

Anyone can set the flag. Treating it as proof of anything invites abuse.

Better Approach

Base security decisions on real authentication and authorisation, never on telemetry headers.

20Best Practices and Common Mistakes

A practical checklist for flags you can trust.

Best practices

  • Use the standard format. Make W3C Trace Context your default, and add other formats only where old systems need them.
  • Check every hop. Gateways, proxies, load balancers and service meshes must pass the trace headers through, with the flags unchanged.
  • Use parent-based sampling everywhere. Let the front door decide, and let everyone else follow.
  • Treat the edge differently. Decide how much to trust incoming flags from outsiders, and apply limits.
  • Let libraries handle headers. Do not build or parse trace headers by hand.
  • Respect reserved bits. Ignore what you do not understand, and never assign your own meaning.
  • Mind the debug gap. If you rely on forced traces, test that they survive across formats and hops.
  • Use flags on logs. Align log keeping with trace sampling, but always keep errors.
  • Watch the numbers. Track the share of flags on, the share of traces kept and the count of broken or invalid headers.
  • Test propagation end to end. Add a simple check that the flag arrives unchanged at the last service.
  • Read the standard when adopting newer flags. Check tool support before you rely on the random flag.

Common mistakes beginners make

  • Thinking trace flags are the same as the trace state, or the baggage.
  • Believing the sampled flag is a command that every service must obey.
  • Confusing “sampled” with “recording”.
  • Reading the two hex characters as a number rather than as switches. “01” means the lowest switch is on, not “one percent”.
  • Dropping the headers for unsampled traces.
  • Hard-coding flag values in manual headers.
  • Expecting the flag on stored spans to show whether tail sampling kept them.
  • Using flags for security decisions.
i
Tip

When a trace looks broken, the first question to ask is, “Did the header with the flags arrive unchanged at each hop?” A quick test is to log the trace header at the entry and exit of each service for a single test request, and compare.

21Real-World and Industry Examples

How trace flags appear in tools and platforms you may already know.

W3C Trace Context

The standard that defines the trace parent header and its flags was developed by the World Wide Web Consortium, with input from major tracing vendors and cloud providers. Its goal was to replace many incompatible headers with one that all products could read, so that a trace can cross company and product boundaries without breaking.

Zipkin and B3

Zipkin popularised passing a sampled value, and a debug value, in request headers, in the format known as B3. Many companies still run services that use it. OpenTelemetry’s B3 propagator translates the sampled idea into the common span context, so mixed systems work together.

Jaeger and Debug Traces

Jaeger, which began at Uber and is now a CNCF project, uses a flags field with a sampled bit and a debug bit, and supports a special header to force a trace for troubleshooting. This is a well-known example of the debug idea that the W3C format does not include.

AWS X-Ray and Google Cloud

AWS X-Ray carries a sampled value in its own trace header, with a special value meaning that the receiver should decide. Google Cloud uses an options value at the end of its own header, where one means the request is traced. OpenTelemetry propagators for both let applications on those clouds take part in traces that cross into other systems.

Proxies and Service Meshes

Proxies such as Envoy, and service meshes built on them, read and write trace headers and can make or follow sampling decisions at the network edge. When they follow the W3C standard, the sampled flag they set is understood by the applications behind them, giving one consistent decision for the whole request path.

A typical journey for a growing company

1

Turn On Default Propagation

Use W3C Trace Context in all services, so flags travel with every request.

2

Fix the Gaps

Find hops that drop or rewrite headers, such as proxies and old libraries, and make them pass headers unchanged.

3

Use Parent-Based Sampling

Let one front door decide and everyone else follow the flag, so traces stay whole.

4

Protect the Edge

Validate incoming headers and limit how far outsiders can force recording.

5

Connect the Signals

Use flags on logs and exemplars to link logs, metrics and traces, and monitor the numbers regularly.

22Frequently Asked Questions

Quick answers to questions beginners ask most.

Q1What are trace flags in one sentence?
They are a one-byte group of on and off switches in the span context that travel with the trace, the best known of which says whether the trace is sampled.
Q2How big are trace flags?
One byte, which is eight bits. In the standard trace parent header, they appear as two hexadecimal characters at the end.
Q3What does the value 01 mean?
The lowest switch is on, which is the sampled flag. It means the trace is being sampled. A value of 00 means no switches are on, so the trace is not sampled.
Q4Is the sampled flag a command?
No. It is a strong hint that describes what the caller did. Receivers usually follow it with parent-based sampling, but they may apply their own rules, especially at public edges.
Q5What is the difference between sampled and recording?
Recording is a local fact about one span collecting details. Sampled is a shared fact in the trace flags saying the trace will be kept. They usually go together, but can differ, for example for a record-only span.
Q6What is the random flag?
A newer switch, defined in recent revisions of the W3C standard, that says the trace ID was generated with proper randomness, so that it can be trusted as a fair lottery number for sampling. Support is still maturing.
Q7What should I do with reserved bits I do not understand?
Ignore them, do not give them your own meaning, and do not reject the header because of them. Set them to zero when you create new flags.
Q8Are trace flags the same as trace state?
No. Flags are fixed standard switches. Trace state is a list of vendor notes. Both are part of the span context, but they have different jobs.
Q9Do I need to pass the trace header when a trace is not sampled?
Yes. Always pass it on, so that the next service learns the decision and does not start a new trace of its own.
Q10Can I change the flags after a span is created?
No. A span context is immutable. To change a flag, a new span context is created with the new value.
Q11What happens to the debug flag from older formats?
The W3C format has no debug flag, so when a debug request is translated, it becomes a plain sampled flag. The fact that it was forced can be lost for downstream services that use only the W3C format.
Q12Do trace flags matter for tail sampling?
Much less. In tail sampling, the real decision is made later in the Collector, after the trace is complete. The flag mainly matters for head sampling, where it carries the early decision.
Q13Can a stranger set the sampled flag on my requests?
Yes, since it travels in a plain header. At public edges, validate the header and apply your own limits so that outsiders cannot force you to record unlimited traces.
Q14Why do logs carry trace flags?
So that logging pipelines can tell whether the linked trace was kept, and align what they keep with the trace policy. For example, they can keep logs of sampled traces in full, and still keep all errors.

23Summary and Key Takeaways

If you remember only a few things, remember these.

Key Takeaways

  • Trace flags are the tick boxes on the trace’s permission slip. They are one byte of on and off switches inside the span context, written as the last two hex characters of the trace parent header.
  • The sampled flag is the one that matters most. Bit zero says whether the trace is being kept, so a single decision at the front door reaches every service without any meeting.
  • It is a strong hint, not a command. Parent-based sampling normally follows it, but receivers can apply their own policy, especially at public edges.
  • Sampled is not the same as recording. Recording is a local fact about a span, and sampled is a shared fact about the trace. Always pass the context on, even when the flag is off.
  • Other bits are for the future. A newer random flag marks trustworthy trace IDs, and the rest are reserved. Ignore unknown bits and never invent your own meanings.
  • The flags connect the signals. They appear on exported spans and on log records, and decide which metric points can carry exemplars that lead to real traces.
  • Protect and verify. Treat incoming flags from strangers as untrusted, validate headers, limit forced recording, test propagation end to end, and never use flags for security decisions.