Skip to main content

What is Distributed Tracing?

Distributed tracing tracks the complete journey of a request as it travels through your system—across services, databases, message queues, and external APIs. Think of it as a GPS for your software: each request generates a trace that shows exactly which components it touched, how long it spent in each one, and where problems occurred.

Unlike traditional monitoring that captures aggregate metrics (averages, percentiles), distributed tracing captures the full context of individual requests. This reveals not just that a system is slow, but why—and often uncovers dependencies and failure modes that metrics alone would miss.

The Anatomy of a Trace

A trace represents a single request and contains:

  • Spans: Discrete operations within the request journey. A span has a start time, end time, and duration. Example spans: "HTTP request received", "database query executed", "cache lookup", "response serialized". Each span records what happened and how long it took.

  • Trace IDs and Span IDs: Unique identifiers that link spans together. Every span in a trace shares the same trace ID, and parent-child relationships are captured via parent span IDs. This creates a tree structure showing the exact flow of the request.

  • Attributes: Key-value metadata attached to spans. Examples: HTTP method, response status code, database host, error messages, user ID, feature flags. Attributes enable filtering and analysis.

  • Timestamps and Duration: Precise timing information showing when each operation started and stopped. This reveals latency bottlenecks.

Example trace structure:

Trace ID: abc123
├─ Span 1: HTTP POST /api/users (0-150ms)
│ ├─ Span 2: Validate input (0-5ms)
│ ├─ Span 3: Query database (5-80ms)
│ │ └─ Span 4: Network round-trip to DB (10-70ms)
│ ├─ Span 5: Send email notification (80-140ms)
│ └─ Span 6: Serialize response (140-150ms)

Context Propagation: When a request crosses service boundaries, trace context (trace ID, span ID, trace flags) must be propagated in request headers. This allows the tracing system to connect spans from different services into one coherent trace. Standards like OpenTelemetry define how context flows across HTTP, gRPC, messaging systems, and other transports.

How Traces Reveal System Behavior

Traces expose system behavior with precision that metrics cannot:

  1. Identify real bottlenecks: See exactly which service or database operation consumed the most time. Example: "Checkout requests spend 80% of time waiting for the payment service, not the main application."

  2. Detect cascading failures: When one service slows down, traces show how latency propagates upstream. Example: "The database query took 5 seconds, which caused the API to time out, which triggered the client to retry, creating a cascade."

  3. Understand service dependencies: Trace data reveals which services depend on which—and which ones are optional or have fallbacks. Example: "The recommendation engine is called on every request, but 30% of traces don't wait for its response."

  4. Correlate errors: See the full chain of events leading to an error. Example: "This request failed because the cache miss forced a database query that exceeded the timeout, which wasn't caught by the caller."

  5. Measure resource impact: Track which operations consume CPU, memory, I/O, and external API calls. This directly ties to cost allocation.

Tracing vs. Logging vs. Metrics

The three observability pillars serve different purposes and work together:

TypePurposeGranularityUse It For
TracingTrack a request's journey through the systemPer-request"Why was this request slow?" or "Where did this error come from?"
LoggingRecord discrete events and errorsPer-event"What happened at this exact time?" or "What were the error details?"
MetricsAggregate system health and performanceSystem-level"Is my service healthy?" or "What's the p99 latency?"

When to use each:

  • Tracing answers "how did this specific request flow through the system?"
  • Logging answers "what events occurred and why?"
  • Metrics answers "what's the aggregate health of my system?"

A production system needs all three. Metrics alert you to problems. Logs help debug them. Traces show you exactly where they occur in your request flow.

Tracing and Cloud Cost Allocation

Distributed tracing directly impacts cost visibility and optimization:

Cost Attribution: Trace data shows which operations consume compute, memory, and external API calls. By attaching customer IDs or feature flags to spans, you can calculate cost-per-customer or cost-per-feature. Example: "Feature X generates 40% of our database queries, which costs $5K/month."

Resource Optimization: Traces reveal which operations are inefficient. Example:

  • A service making redundant API calls to a third-party service ($100/month in wasted calls)
  • A slow database query running on every request instead of being cached
  • A synchronous operation that could be async, blocking resources

Service Dependency Mapping: Understanding which services are called by which requests helps right-size infrastructure and identify candidates for optimization or removal.

Cost-Performance Trade-offs: Tracing shows the actual cost of different architectural choices. Example: "Caching this lookup reduces database cost by 30% with no latency penalty" or "Using this synchronous API adds $2K/month in compute cost for minimal UX improvement."

Without tracing, optimizing cloud costs becomes guesswork. With tracing, every dollar spent on compute, storage, and APIs can be tied back to specific business operations or customer segments.

How Tracing Works in Practice

Most distributed tracing systems follow this flow:

  1. Instrumentation: Code libraries or agents automatically capture spans when your application performs operations (HTTP requests, database queries, etc.). Developers can also add custom spans for business logic.

  2. Context Propagation: When requests cross service boundaries, trace context is passed in headers or metadata, allowing the tracing system to connect spans from different services.

  3. Span Collection: Spans are collected locally and sent to a tracing backend (often via an agent process to avoid blocking).

  4. Span Storage: The backend stores traces in a time-series database or object store optimized for trace data.

  5. Querying and Visualization: The UI lets developers search traces by trace ID, service, duration, error status, or custom attributes. Visualization shows the trace timeline.

Standards: OpenTelemetry is the industry standard for tracing instrumentation. It provides vendor-neutral SDKs for instrumenting applications in multiple languages, and standards for how context should propagate across services. OpenTelemetry is built into many observability platforms (Datadog, New Relic, Jaeger, Lightstep, etc.).

Tradeoffs:

  • Tracing adds overhead (network, CPU for instrumentation). Modern systems sample traces to reduce this.
  • Storing every trace is expensive; teams typically retain full traces for errors/slow requests and sampled traces for normal traffic.
  • Tracing requires instrumentation work; it doesn't magically appear without code changes or agent deployment.