This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
devopscritical PriorityID: opentelemetry-async-span-linking-boundary-standard

OpenTelemetry Asynchronous Span Linking & Trace Context Boundary Standard

Mandates explicit OpenTelemetry span linking across asynchronous message queues, event brokers, and detached background jobs instead of forging synthetic parent-child hierarchies. Ensures consumer execution latency is decoupled from producer trace lifespans while maintaining full bidirectional causal graph integrity in distributed telemetry backends.

Prohibited Anti-Pattern: Forging direct parent-child trace spans across decoupled messaging brokers causing corrupted trace graphs and unbounded parent durations.

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenTelemetry Asynchronous Span Linking & Trace Context Boundary Standard - Mandates explicit OpenTelemetry span linking across asynchronous message queues, event brokers, and detached background jobs instead of forging synthetic parent-child hierarchies. Ensures consumer execution latency is decoupled from producer trace lifespans while maintaining full bidirectional causal graph integrity in distributed telemetry backends.
globs: src/**/*.ts, src/**/*.js, src/queues/**/*.ts, src/consumers/**/*.ts, src/producers/**/*.ts, src/events/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/opentelemetry-async-span-linking-boundary-standard"
---

# OpenTelemetry Asynchronous Span Linking & Trace Context Boundary Standard

> **Severity**: CRITICAL | **Category**: devops
> **Anti-Pattern Warning**: Forging direct parent-child trace spans across decoupled messaging brokers causing corrupted trace graphs and unbounded parent durations.

## System Constraints
You are a Principal Observability Architect enforcing OpenTelemetry distributed tracing standards across asynchronous messaging systems. You strictly prevent developers from binding consumer execution spans as direct children of producer context, which distorts trace durations and corrupts critical path analyses. You mandate the use of OpenTelemetry Span Links for decoupled messaging patterns and batch consumer boundaries.

## Strict Guidelines
- Engineers MUST ALWAYS extract message carrier context using `propagation.extract()` and bind the resulting context via `links` when initiating consumer message processing spans.
- Engineers MUST NOT pass an extracted asynchronous message context directly as the parent context (`context.with(extractedContext, ...)` or `{ parent: ... }`) for detached, out-of-band asynchronous jobs.
- Consumer receive/poll spans MUST represent only the transport layer retrieval operation; message processing logic MUST be wrapped in a separate span linking back to each respective message context.
- Batch consumers processing multiple records MUST NEVER assign multiple parent spans to a single processing block; each message within the batch MUST be processed in a dedicated span linking to its original producer context.
- Producers MUST ALWAYS inject W3C Trace Context (`traceparent`, `tracestate`) into message headers/attributes using `propagation.inject()` prior to broker dispatch.

## Bad vs Good Implementations
### Kafka Consumer Message Processing: Direct Parent vs. Linked Context

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Activating extractedContext as the direct parent creates an artificial synchronous dependency in APM visualization. If a message sits in a queue for 10 minutes, the root producer trace appears to have taken 10 minutes, skewing SLA metrics, distributed flame graphs, and latency percentiles.
```typescript
import { trace, context, propagation, defaultTextMapGetter } from '@opentelemetry/api';

interface Message {
  headers: Record<string, string>;
  value: string;
}

export async function handleMessage(message: Message): Promise<void> {
  const tracer = trace.getTracer('order-worker');
  
  // ANTI-PATTERN: Activating extracted context as the active parent.
  // This causes the consumer span to become an inline child of the producer,
  // misrepresenting execution time as part of the originating HTTP request trace.
  const extractedContext = propagation.extract(context.active(), message.headers, defaultTextMapGetter);

  await context.with(extractedContext, async () => {
    const span = tracer.startSpan('process_order');
    try {
      await executeOrder(message.value);
      span.setStatus({ code: 1 });
    } catch (err) {
      span.recordException(err as Error);
      span.setStatus({ code: 2 });
      throw err;
    } finally {
      span.end();
    }
  });
}

async function executeOrder(_val: string): Promise<void> {}

```

#### Production Standard (Correct)
> **Standard**: Creates a distinct root trace for consumer execution while preserving the causal graph via OpenTelemetry Span Links. The producer span's duration remains unaffected, while modern APM tools (e.g., Jaeger, Datadog, Honeycomb) render the link between the producer and consumer traces without falsifying execution lifecycles.
```typescript
import { trace, context, propagation, defaultTextMapGetter, SpanKind } from '@opentelemetry/api';

interface Message {
  headers: Record<string, string>;
  value: string;
}

export async function handleMessage(message: Message): Promise<void> {
  const tracer = trace.getTracer('order-worker');

  // 1. Extract context from incoming message attributes
  const extractedContext = propagation.extract(context.active(), message.headers, defaultTextMapGetter);
  const linkedSpanContext = trace.getSpanContext(extractedContext);

  // 2. Start a fresh root consumer span and explicitly link the causal producer span
  const span = tracer.startSpan('process_order', {
    kind: SpanKind.CONSUMER,
    links: linkedSpanContext ? [{ context: linkedSpanContext }] : [],
    attributes: {
      'messaging.system': 'kafka',
      'messaging.operation': 'process',
    },
  });

  // 3. Execute work within the local consumer span context
  await context.with(trace.setSpan(context.active(), span), async () => {
    try {
      await executeOrder(message.value);
      span.setStatus({ code: 1 });
    } catch (err) {
      span.recordException(err as Error);
      span.setStatus({ code: 2, message: (err as Error).message });
      throw err;
    } finally {
      span.end();
    }
  });
}

async function executeOrder(_val: string): Promise<void> {}

```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: OpenTelemetry Asynchronous Span Linking & Trace Context Boundary Standard

OpenTelemetry Asynchronous Span Linking & Trace Context Boundary Standard defines an industrial-grade behavioral standard for devops engineering. Mandates explicit OpenTelemetry span linking across asynchronous message queues, event brokers, and detached background jobs instead of forging synthetic parent-child hierarchies. Ensures consumer execution latency is decoupled from producer trace lifespans while maintaining full bidirectional causal graph integrity in distributed telemetry backends. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Forging direct parent-child trace spans across decoupled messaging brokers causing corrupted trace graphs and unbounded parent durations. Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftForging direct parent-child trace spans across decoupled messaging brokers causing corrupted trace graphs and unbounded parent durations.Critical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS extract message carrier context using `propagation.extract()` and bind the resulting context via `links` when initiating consumer message processing spans.

Engineers MUST ALWAYS extract message carrier context using `propagation.extract()` and bind the resulting context via `links` when initiating consumer message processing spans.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT pass an extracted asynchronous message context directly as the parent context (`context.with(extractedContext, ...)` or `{ parent

Engineers MUST NOT pass an extracted asynchronous message context directly as the parent context (`context.with(extractedContext, ...)` or `{ parent: ... }`) for detached, out-of-band asynchronous jobs.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Consumer receive/poll spans MUST represent only the transport layer retrieval operation

Consumer receive/poll spans MUST represent only the transport layer retrieval operation; message processing logic MUST be wrapped in a separate span linking back to each respective message context.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Batch consumers processing multiple records MUST NEVER assign multiple parent spans to a single processing block

Batch consumers processing multiple records MUST NEVER assign multiple parent spans to a single processing block; each message within the batch MUST be processed in a dedicated span linking to its original producer context.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Producers MUST ALWAYS inject W3C Trace Context (`traceparent`, `tracestate`) into message headers/attributes using `propagation.inject()` prior to broker dispatch.

Producers MUST ALWAYS inject W3C Trace Context (`traceparent`, `tracestate`) into message headers/attributes using `propagation.inject()` prior to broker dispatch.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is OpenTelemetry Asynchronous Span Linking & Trace Context Boundary Standard critical for AI coding assistants?

Mandates explicit OpenTelemetry span linking across asynchronous message queues, event brokers, and detached background jobs instead of forging synthetic parent-child hierarchies. Ensures consumer execution latency is decoupled from producer trace lifespans while maintaining full bidirectional causal graph integrity in distributed telemetry backends. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Forging direct parent-child trace spans across decoupled messaging brokers causing corrupted trace graphs and unbounded parent durations.) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

OpenTelemetry