Trace IDs, Segments, and Propagation
coreintermediateA trace follows one request through every service that handled it. Each service sends a segment describing its own work; a segment breaks down into subsegments for downstream calls it made. What ties them together is a trace ID carried in an HTTP header — `X-Amzn-Trace-Id` for X-Ray — added by the first traced service and passed along by everything after it.
Think of it as
A trace is a parcel-tracking number. Each depot scans the same number and records when it received and forwarded the parcel. Nobody has the whole journey; the number is what lets you assemble it afterwards. Lose the number at one depot and the journey splits into two unrelated deliveries.
What we're doing: See why a trace stops halfway through and the second half appears as a separate, parentless trace.
- 4
- Propagation over synchronous HTTP is usually handled for you by the instrumented HTTP client — this half works without anyone thinking about it.
- 7
- An asynchronous hop has no HTTP headers to carry the context. The trace ID has to be put into the message and read back out by the consumer, deliberately.
Why this works: Tracing looks automatic because the SDK instruments HTTP clients for you. Every hop that is not an HTTP call — a queue, a stream, a scheduled job — is a place where the trace context has to be carried by hand, and where it silently is not.
Trusting an incoming X-Amzn-Trace-Id header on a public endpoint
Wrong
Better
What you see: Traces from unrelated requests merge together, or every request arrives already marked `Sampled=1` and the tracing bill rises far above the configured sampling rate.
Why: AWS documents this directly: a tracing header can originate from the client request, so an application should remove `X-Amzn-Trace-Id` from incoming requests to avoid users adding trace IDs or sampling decisions of their own. The sampling decision in particular controls spend.
- Client → API: POST /checkout (No trace header yet)
- API → API: Adds Root=1-5759e988-…;Sampled=1 (Segment: API)
- API → Orders service: POST /orders + same Root, Parent=API segment id (Subsegment on API, segment on Orders)
- Orders service → DynamoDB: PutItem (Subsegment only — DynamoDB sends no segment, so X-Ray infers one)
- DynamoDB → Orders service: 200
- Orders service → API: 201
The tracing header fields
Together
Remember: Segments (one per service) + subsegments (one per downstream call) grouped by a trace ID = a trace. `X-Amzn-Trace-Id` carries Root / Parent / Sampled, added at the front door and propagated onward — and every non-HTTP hop is somewhere you must carry it yourself.
See also: sampling annotations and filter expressions · attributing latency across tiers

