- Definition and motivation for span links
- Common async and parallel scenarios where links matter
- Key differences vs. parent-child spans
- OpenTelemetry Link usage with a code example
- Practical use cases and best practices

Why span links matter
Traditional tracing models a strict parent → child call hierarchy. But modern systems frequently:- Execute work asynchronously (e.g., tasks enqueued and processed later)
- Run parallel workers for a single logical job
- Use message brokers where producer and consumer are independent processes

Example scenario
- A user places an order on an e-commerce site. The front-end service creates an
order-confirmationspan for the incoming request. - The order processing service publishes messages to a queue for downstream consumers.
- Separate consumers independently process those messages: one sends the confirmation email, another updates inventory.
- The email and inventory spans are not children of the original order-confirmation span (they run in different processes), but they are logically tied to the same order.

Batch, asynchronous, and parallel processing
Common patterns that benefit from links:- Batch jobs / Map-Reduce: multiple worker spans handle partitions of a job; links relate each worker to the initiating job span.
- Message aggregation: combine results from several messages into a single aggregate result; link each message-processing span to the aggregator span.
- Transactional messaging & event sourcing: relate event-processing spans and participating messages back to a transaction or final entity state.

Key differences
-
Parent-child spans:
- Represent a strict hierarchy and direct cause/effect.
- Child spans typically inherit context from the parent.
- Useful for synchronous request/response call chains.
-
Span links:
- Represent loose contextual associations between independently started spans.
- Spans may be created in different processes, at different times, or in parallel.
- Useful for async processing, queues, event-driven flows, and batch work.

OpenTelemetry: the Link concept
OpenTelemetry exposes a Link construct to attach a span context (and optional attributes) to a newly created span. A Link typically contains the target span context and metadata such as anorder.id or message.id. Links are recorded on the new span and allow backends to correlate traces and perform richer analysis.
Example (Python, OpenTelemetry):
Use span links when related work is produced and consumed asynchronously, when multiple independent workers process parts of a single logical operation, or when you need to associate messages and events without creating parent-child spans.
Practical use cases
- Scatter-gather / Map-Reduce: link each worker span to the initiating job span.
- Message aggregation: link each message-processing span to the aggregator span.
- Transactional messaging: trace participating messages in a distributed transaction via links.
- Event sourcing: associate event-processing spans to the originating action or final state.
order.id, message.id, job.id) so backend systems can filter and join related spans.

Quick comparison table
| Model | When to use | Example |
|---|---|---|
| Parent-Child | Synchronous call chains where one operation directly invokes another | Service A calls Service B over HTTP |
| Span Links | Asynchronous, parallel, or otherwise independent work that shares a trigger/context | Workers consuming messages related to the same order |
Summary
Span links are a core OpenTelemetry feature for connecting related spans that are not in a parent-child relationship. They enable accurate tracing of modern asynchronous, parallel, and message-driven systems by allowing independent spans to reference one another via context and attributes.
Links and references
- OpenTelemetry specification — Tracing: https://opentelemetry.io/docs/specs/trace/
- OpenTelemetry Python documentation: https://opentelemetry.io/docs/instrumentation/python/
- Distributed tracing concepts: https://opentracing.io/ (conceptual background)