Sentry Distributed Tracing: Minimal Design, Sampling, and Trust Boundaries
Add cross‑service visibility with Sentry’s built‑in tracing by enabling a single tracesSampleRate and letting SDKs propagate sentry‑trace and baggage headers. This note explains the smallest design, trust limits, operational checks and failure modes that shape the right sampling strategy.
12 Dec 2025, 01:12 UTC

Problem & Takeaway
When a request flows through multiple services you want a single, coherent trace in Sentry’s UI. The simplest way to achieve that is to let each SDK automatically attach a sentry-trace header (and, in newer releases, a baggage header) to outgoing HTTP calls. With a single tracesSampleRate or a tracesSampler callback you can control how many traces are kept, keeping the design minimal while still providing cross‑service visibility.
Requirements & Minimal Design
- All services expose a Sentry SDK that supports performance tracing.
- Each SDK is configured with a DSN and a sampling strategy.
- SDKs propagate
sentry-traceandbaggageheaders on outbound HTTP requests. - No additional instrumentation infrastructure is needed beyond the existing Sentry event pipeline.
The smallest suitable design is therefore:
- Enable performance tracing in every SDK.
- Set a uniform
tracesSampleRate(e.g.,0.1for 10 % sampling). - Keep the default header propagation logic; no custom middleware is required.
Example: Node.js Backend
const Sentry = require('@sentry/node');
Sentry.init({
dsn: <YOUR_DSN>,
tracesSampleRate: 0.1, // 10% of transactions are kept
beforeSendTransaction: (event, hint) => {
// optional: drop slow transactions
return event;
},
});
With this configuration every incoming HTTP request creates a root transaction. When the backend calls another service, the SDK automatically adds the sentry-trace header to the outgoing request.
Trust & Data Boundaries
Headers coming from external clients (browsers, mobile apps, third‑party services) are attacker‑controlled. Treat them as untrusted at the network edge.
- Forged sampled flag: A client could set
sampled=1to force trace retention, inflating your quota. - Forged trace ID: A malicious ID could pollute trace continuity and mislead analysis.
- Baggage content: Because baggage can carry arbitrary key/value pairs, avoid placing PII or secrets in it.
Only the SDK verifies that the sampled flag matches the service’s own sampling decision for outgoing calls. All other header values are passed through unchanged.
Operational Checks
- Verify header propagation: In a test environment, make a request from Service A to Service B. Inspect Service B’s logs or devtools to confirm the
sentry-traceheader is present and its trace ID matches the one displayed in Sentry. - Check sampling quota: Compare the number of transactions in Sentry’s usage page against expected traffic ×
tracesSampleRateto ensure the sampler is behaving as configured. - Inspect trace continuity: In the Sentry UI, open a trace that spans multiple services and verify that the parent/child relationships match the
parent_span_idvalues in the header.
Failure Modes & Mitigations
- Header stripping: Proxies or allowlists that remove
sentry-tracebreak continuity. Mitigation: whitelist the header in load balancers and reverse proxies. - Mismatched sampling decisions: If two chained services use different
tracesSampleRatevalues, some traces may become orphaned. Mitigation: keep a consistent rate or use atracesSamplerthat aligns decisions. - Clock skew: Significant differences between host clocks can distort waterfall timelines. Mitigation: NTP sync on all hosts.
- Missing instrumentation: A service that lacks tracing will create a gap that looks like a dropped request. Mitigation: audit all entry points to ensure tracing is enabled.
When the Design Needs to Change
- High event volume: If the uniform rate is too low to meet SLA visibility, consider dynamic sampling via
tracesSamplerthat adapts to traffic spikes. - Full trace coverage required: For compliance or deterministic debugging, statistical sampling is insufficient. You would need to set
tracesSampleRate=1.0or switch to a custom exporter. - Migration to OpenTelemetry: When moving to an OpenTelemetry‑based stack, you’ll need to map Sentry’s span model to OTLP, which may require additional instrumentation code.
- Self‑hosted vs SaaS differences: Some features (e.g., dynamic sampling) are only available on Sentry SaaS or newer self‑hosted releases. Verify feature availability for your deployment before relying on them.
Summary Table: Header Fields & Meaning
| Header | Format | Meaning |
|---|---|---|
sentry-trace | trace_id|span_id|sampled | Propagates the current trace ID, parent span ID, and sampling decision. |
baggage | key1=value1,key2=value2 | Optional metadata carried across services; avoid PII. |
| traceparent (OTLP) | version-format-trace-id-span-id-flags | OTLP equivalent; Sentry SDKs emit it alongside sentry-trace if OpenTelemetry is enabled. |
Conclusion
Enabling Sentry distributed tracing with a single tracesSampleRate and the SDK’s automatic header propagation is the lowest‑complexity path to cross‑service visibility. By respecting trust boundaries, performing routine operational checks, and anticipating failure modes, you can maintain reliable traces without adding extra infrastructure. Only when you hit volume limits, need deterministic trace coverage, or migrate to OTLP should you consider moving beyond this minimal design.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.