
- It provides semantic information that tracing backends use to interpret relationships between spans (for example, to connect outgoing requests to the service that received them).
- It indicates whether an interaction is synchronous (request/response) or asynchronous (message-based), which affects how traces are visualized and analyzed.
- It helps maintain correct parent-child relationships across process or service boundaries when context is propagated.

CLIENT, SERVER, INTERNAL, PRODUCER, and CONSUMER. Use the kind that best represents the role of the span so tracing tools can correctly link and display causal relationships.

| Span Kind | Direction | Communication style | Typical use case |
|---|---|---|---|
CLIENT | Outgoing | Synchronous request/response | HTTP requests, RPC calls, DB queries |
SERVER | Incoming | Synchronous request/response | Web server handling an HTTP request |
INTERNAL | Local | In-process work (no boundary crossing) | Computations, helper functions, local processing |
PRODUCER | Outgoing (message) | Asynchronous/message-based | Publishing to a Kafka topic or message queue |
CONSUMER | Incoming (message) | Asynchronous/message-based | Processing messages consumed from a queue or topic |
- Correct kinds enable accurate trace analysis and visualization (dependency maps, service flow graphs).
- They reduce ambiguity: each span should represent a single, clear purpose.
- They ensure propagation and linking work as intended across service boundaries.

CLIENT: Outgoing calls (HTTP requests, RPC, DB queries). Create a newCLIENTspan for each external call so each request is represented individually.SERVER: Incoming requests handled by a service. When context is propagated, theSERVERspan becomes a child of the originatingCLIENTspan.PRODUCER: Enqueuing or publishing a message (e.g., writing to a Kafka topic).CONSUMER: Receiving and processing a message from a broker or queue.INTERNAL: Local in-process operations that do not cross service boundaries (default kind when none is set).

- Client side: creating an outgoing HTTP request should produce a
CLIENTspan. - Server side: receiving that request produces a
SERVERspan. - When headers (or another propagation mechanism) carry trace context, the server span becomes a child of the client span, forming a clear client→server causal link in the trace.

PRODUCERspans represent the act of publishing or enqueueing a message.CONSUMERspans represent the processing of that message by consumers.- Any additional local work done while processing a message (parsing, business logic) should use
INTERNALspans to reflect in-process operations.

- Give each span one clear role — do not mix
CLIENTandSERVERresponsibilities in a single span. - When a call crosses a process or service boundary, set the appropriate span kind to help tracing backends visualize relationships.
- Create separate
CLIENTspans for each outgoing operation (e.g., multiple DB calls should each have their ownCLIENTspan). - For async flows, use
PRODUCERandCONSUMERand preserve causal links via context propagation or explicit span links.

- Span kinds are essential for meaningful tracing: they indicate direction, communication style, and clarify cause-effect relationships.
- Use
CLIENT/SERVERfor synchronous request/response; usePRODUCER/CONSUMERfor messaging; default toINTERNALfor local operations. - Avoid overloading spans with multiple roles; create distinct spans for separate outgoing operations to keep traces clear and accurate.

Most spans you create locally will be
INTERNAL. Reserve CLIENT, SERVER, PRODUCER, and CONSUMER for interactions that cross process or service boundaries.- OpenTelemetry Spec — Span Kind semantic conventions: https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/span-kind/
- Kafka documentation (example messaging system): https://kafka.apache.org/documentation/