Distributed Tracing
See the whole journey of one request in a single timeline: which services it went through and how much time it took at each place.
45.1 Why is it used?
- In microservices one checkout request passes through 10-20 services; finding which is slow from logs is hard.
- The latency bottleneck (a slow DB query, a slow third-party API) shows up directly on the timeline.
- A service dependency map gets built: who calls whom.
- You learn which service errors started in and how far the failures spread.
- Together with logs and metrics it completes the third pillar of observability.
45.2 How it works
- Trace: the journey of one whole request, with a unique trace_id.
- Span: one step of a trace (like "DB query" or "payment API call"), with start time, duration and tags; spans form a parent-child tree.
- Context propagation: trace_id and span_id travel to the next service in an HTTP header (W3C traceparent) or a Kafka message header.
- Instrumentation: the OpenTelemetry SDK/auto-instrumentation creates spans by itself on HTTP, DB and gRPC calls.
- Collector: the OTel Collector receives, processes and batches spans and sends them to a backend like Jaeger, Tempo, X-Ray or Datadog.
- Sampling: tracing every request is expensive; head sampling (1-10% random) or tail sampling (keep only slow/error traces).
- Put trace_id in logs so that the related logs open directly from a trace.
- 1.API Gateway: trace_id is created, header traceparent: 00-4bf92f...(trace_id)-00f067...(span_id)-01
- 2.Cart svc, Restaurant svc, Payment svc, Bank API: each service forwards the header and creates its own span (OTel SDK)
- 3.OTel Collector: batch + sampling (1-10% or tail)
- 4.Jaeger / Tempo: trace UI
If context propagation breaks (the header is not passed through a queue or thread pool), the trace is cut in the middle.
- 1.api-gateway: place-order 3.65s (gateway 20ms)
- 2.cart-svc 50ms
- 3.restaurant-svc 80ms
- 4.payment-svc 3.5s, with a child span inside: bank API call 3.3s (bottleneck)
- 5.Search logs by trace_id: found "retry 3 times"
- 6.Fix: timeout + circuit breaker + async bank call, p99 4s -> 600ms, verified in Grafana
Put trace_id in logs so that logs open directly from the trace.
45.3 Tools you can use
| Tool | Type | How it is used |
|---|---|---|
| OpenTelemetry (OTel) | Open standard + SDKs (CNCF) | Generates and exports traces, metrics, logs in a vendor-neutral way; you can change the backend later. |
| Jaeger | Open-source tracing backend (CNCF) | Stores traces and shows the timeline and dependency graph in a UI; built by Uber. |
| Zipkin | Open-source tracing backend | An older, simple tracing system built by Twitter; easy for small setups. |
| AWS X-Ray | AWS managed tracing | Traces and a service map for Lambda, API Gateway, ECS; data can also be sent via ADOT (AWS Distro for OTel). |
| Grafana Tempo | Open-source tracing backend | Cheap trace storage in object storage, linked in Grafana with Loki logs and Prometheus metrics. |
| Datadog APM | Commercial SaaS APM | Automatic traces through the agent, correlated in one UI with metrics and logs. |
45.4 Comparison: Jaeger vs Zipkin vs AWS X-Ray (OpenTelemetry works with all)
| Point | Jaeger | Zipkin | AWS X-Ray |
|---|---|---|---|
| Type | Open-source, self-hosted | Open-source, self-hosted | AWS managed service |
| Origin | Uber, CNCF graduated | Twitter, inspired by the Google Dapper paper | AWS |
| Storage | Cassandra, Elasticsearch/OpenSearch, Badger | Cassandra, Elasticsearch, MySQL, memory | AWS managed, nothing to manage |
| OpenTelemetry support | Native OTLP support | Via an OTel exporter | Via the ADOT collector |
| Scaling | Good, but you handle the cluster yourself | For small-to-medium setups | AWS auto scale |
| Cost | Free, infra cost | Free, infra cost | Pay per trace recorded/scanned |
| Best for | Kubernetes microservices, large scale | Simple, legacy Java/Spring setups | AWS Lambda/serverless apps |
45.5 When to choose which
- Always instrument with OpenTelemetry so you can change the backend (Jaeger/X-Ray/Datadog) later without code changes.
- Jaeger / Tempo: when you want a self-hosted, open-source stack on Kubernetes.
- Zipkin: a small or older Spring Boot setup where it is already integrated.
- AWS X-Ray: a serverless/AWS-native app where you want zero ops.
- Datadog APM: when you already use paid all-in-one observability.
45.6 Real-world example
Such a scenario: "Place Order" is slow in a food delivery app
- Users say placing an order takes 4 seconds, and p99 latency is up on the dashboards.
- An engineer filters the slow traces of "place-order" in Jaeger (duration > 3s).
- The trace timeline shows: API gateway 20ms, cart service 50ms, restaurant service 80ms, payment service 3.5s.
- The child span inside the payment span shows that the third-party bank API call alone takes 3.3s.
- They copy the trace_id and search the logs, where they find "retry 3 times" logs.
- The team adds a timeout + circuit breaker and makes the bank call async; p99 comes back to 600ms.
45.7 Interview tips
- Forgetting context propagation (not passing the header through an async queue or thread pool) makes the trace break in the middle.
- Keeping 100% sampling in production makes storage and network cost balloon.
- Not putting trace_id in logs means traces and logs cannot be linked.
- Interview tip: explain the difference between trace, span and log, and the sampling strategy.