Prompt
How do I trace a request across microservices
Latest observation
To trace a request across microservices, you want to give every request a shared correlation ID / trace context and propagate it through all services, logs, and telemetry.
The usual approach
1) Generate a trace ID at the entry point
At the edge of your system—API gateway, load balancer, or first service—create a unique ID for the request if it doesn’t already have one.
Common names:
trace_idcorrelation_idrequest_id
2) Propagate it in headers
Pass that ID to every downstream service in HTTP/gRPC/message queues.
Common headers:
- W3C Trace Context:
traceparent,tracestate - B3 (Zipkin):
X-B3-TraceId,X-B3-SpanId, etc. - Custom:
X-Request-IdorX-Correlation-Id
Best practice today: use W3C Trace Context if possible.
3) Create spans for each hop
A trace is made of spans:
- One span per service call or important operation
- Each span has:
trace_idshared across the requestspan_idunique to that stepparent_span_idlinking to the caller
This gives you a tree of work across services.
4) Log the trace ID everywhere
Add the trace ID to application logs in every service so you can search logs and connect them to traces.
Example log line:
2026-10-03T12:00:01Z service=orders trace_id=abc123 span_id=def456 msg="calling inventory"
5) Use distributed tracing tooling
Instrument your services with something like:
- OpenTelemetry for instrumentation
- Jaeger, Zipkin, Grafana Tempo, Datadog, New Relic, Honeycomb for storage/visualization
OpenTelemetry is the current standard choice because it supports many languages and backends.
Example flow
- Client sends request to
api-gateway - Gateway creates
trace_id=123 - Gateway calls
orders-servicewith same trace context orders-servicecreates a child span and callsinventory-serviceinventory-servicecreates another child span- All logs/spans can be queried using trace
123
Minimal implementation pattern
Incoming request
- Check for existing trace headers
- If absent, create a new trace context
- Store it in request context / MDC / thread-local / async context
Outgoing request
- Inject current trace context into headers
- Ensure async/background jobs also carry it forward
Logging
- Configure your logger to include trace/span IDs automatically
If you want the simplest practical setup
- Add OpenTelemetry SDK to each service
- Configure an exporter to Jaeger/Tempo/Zipkin
- Enable automatic HTTP/gRPC instrumentation
- Make sure logs include
trace_idandspan_id - Use trace context propagation in queues and async jobs too
Common pitfalls
- Forgetting to propagate headers across services
- Not propagating context through async tasks/threads
- Using a different ID format in each service
- Logging without trace IDs
- Sampling too aggressively and missing important traces
Rule of thumb
If you can answer:
- “What happened?”
- “Where did it go?”
- “Which service was slow or failed?”
…then your tracing is working.
If you want, I can show you:
- a language-specific example (Node, Java, Python, Go, .NET), or
- an OpenTelemetry setup for a microservices stack.