Problem
One user action fans out across many services, queues, and databases, each writing separate logs. Without a shared key, reconstructing what happened to a single request means guessing from timestamps.
Also known as: request-ids, trace-context-propagation
Attach a unique identifier to each request and propagate it through every hop so related logs and events can be joined.
One user action fans out across many services, queues, and databases, each writing separate logs. Without a shared key, reconstructing what happened to a single request means guessing from timestamps.
A correlation ID is a unique token that follows a request across services. Every log line, span, and event produced for that request carries the same value, so a single search reconstructs the story. It is the cheapest form of distributed observability.
At the edge, middleware reads the header or creates a new identifier, then puts it in context. Outgoing clients read it from context and send it onward.
client -> gateway: (none)
gateway: id = new_id() # 7f3a9c...
gateway -> orders: X-Request-ID: 7f3a9c
orders -> payments: X-Request-ID: 7f3a9c
orders -> queue: message header request_id=7f3a9c
every log: {"request_id":"7f3a9c","svc":"orders","msg":"..."}
For asynchronous work, put the ID in message headers and restore it in the consumer's context. If one message triggers many, keep the original as a parent or causation ID and mint a new ID per child so that the relationship is still traceable. Return the ID in error responses and show it in the UI error page, so support can search logs immediately.
When tracing is deployed, use the W3C traceparent header; the trace ID then doubles as the correlation ID and links logs to spans.
Low - header propagation
Low - library or middleware
Low - simple concept
Identifier dropped at an async boundary, breaking the chain
Client-supplied value injected into logs, enabling log forging
IDs reused across retries so distinct attempts cannot be told apart