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

OpenTelemetry W3C Span Link Invariant for Decoupled Asynchronous Saga Tracing

Enforces causal trace lineage decoupling in asynchronous sagas by mandating OpenTelemetry W3C span links over direct parent-child span propagation. This prevents runaway trace cascades and downstream APM storage quota exhaustion while preserving distributed provenance across message brokers.

Prohibited Anti-Pattern: Direct Child Span Inheritance Across Asynchronous Message Boundaries Causing APM Quota Blowout

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenTelemetry W3C Span Link Invariant for Decoupled Asynchronous Saga Tracing - Enforces causal trace lineage decoupling in asynchronous sagas by mandating OpenTelemetry W3C span links over direct parent-child span propagation. This prevents runaway trace cascades and downstream APM storage quota exhaustion while preserving distributed provenance across message brokers.
globs: src/**/*.consumer.ts, src/**/*.handler.ts, src/**/messaging/**/*.ts, src/**/saga/**/*.ts, src/**/*.worker.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/opentelemetry-span-link-sampling-async-saga"
---

# OpenTelemetry W3C Span Link Invariant for Decoupled Asynchronous Saga Tracing

> **Severity**: CRITICAL | **Category**: devops
> **Anti-Pattern Warning**: Direct Child Span Inheritance Across Asynchronous Message Boundaries Causing APM Quota Blowout

## System Constraints
You are a Principal Software Architect enforcing OpenTelemetry W3C distributed tracing standards across event-driven architectures and distributed sagas. You MUST forbid consumers from setting extracted message span contexts as direct active parents of consumer execution spans. Mandate OpenTelemetry Span Links rooted at ROOT_CONTEXT with autonomous downstream sampling decisions.

## Strict Guidelines
- Engineers MUST ALWAYS extract upstream trace context using `propagation.extract(ROOT_CONTEXT, carrier)` to access the producer's SpanContext.
- Engineers MUST NOT pass an extracted message SpanContext directly to `context.with()` or set it as the parent context of consumer processing spans.
- Services MUST instantiate consumer processing spans as new root spans (or children of the consumer framework context) explicitly attaching the extracted SpanContext via the `links` option: `links: [{ context: extractedSpanContext }]`.
- Engineers MUST ensure consumer spans evaluate their own local sampling rules rather than blindly inheriting upstream sampled flags that blow APM storage quotas.
- Code SHOULD enrich the Span Link with semantic messaging attributes such as `messaging.operation: 'process'` and `messaging.system` to preserve causal relationship intent.
- Components NEVER drop upstream W3C headers (`traceparent`, `tracestate`); they must be parsed into Span Links even if the consumer span itself is non-sampled.

## Bad vs Good Implementations
### Asynchronous Message Consumer Context Handling

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Directly activating the extracted context ties the consumer's lifecycle to the producer's trace ID. In asynchronous sagas spanning hours or days, this produces pathological trace sizes, exceeds APM span-depth limits, and forcibly bypasses downstream sampling controls, exhausting APM ingest quotas.
```typescript
import { trace, propagation, context } from '@opentelemetry/api';
import { ConsumeMessage } from 'amqplib';

const tracer = trace.getTracer('order-saga-worker');

export async function handleOrderEvent(msg: ConsumeMessage): Promise<void> {
  const headers = msg.properties.headers ?? {};
  // ANTI-PATTERN: Extracting and directly applying parent context makes the consumer
  // span a child of the producer span. This creates massive, unprunable trace graphs
  // across long-running sagas and forces 100% downstream ingestion when upstream is sampled.
  const parentContext = propagation.extract(context.active(), headers);

  await context.with(parentContext, async () => {
    await tracer.startActiveSpan('process_order_event', async (span) => {
      try {
        await processMessagePayload(msg.content);
        span.setStatus({ code: 1 }); // OK
      } catch (err) {
        span.recordException(err as Error);
        throw err;
      } finally {
        span.end();
      }
    });
  });
}
```

#### Production Standard (Correct)
> **Standard**: Extracting the producer context and supplying it as a Span Link while starting the consumer span from `ROOT_CONTEXT` decouples trace lifecycles. Downstream head/tail samplers retain full autonomy over ingestion quotas without severing causal DAG topology in distributed APM visualizations.
```typescript
import { trace, propagation, ROOT_CONTEXT, SpanKind, Link } from '@opentelemetry/api';
import { ConsumeMessage } from 'amqplib';

const tracer = trace.getTracer('order-saga-worker');

export async function handleOrderEvent(msg: ConsumeMessage): Promise<void> {
  const headers = msg.properties.headers ?? {};
  // Extract carrier into an isolated context
  const extractedContext = propagation.extract(ROOT_CONTEXT, headers);
  const producerSpanContext = trace.getSpanContext(extractedContext);

  const links: Link[] = [];
  if (producerSpanContext && trace.isSpanContextValid(producerSpanContext)) {
    links.push({
      context: producerSpanContext,
      attributes: {
        'messaging.operation': 'process',
        'messaging.system': 'rabbitmq'
      }
    });
  }

  // PRODUCTION INVARIANT: Start a decoupled span from ROOT_CONTEXT with a span link.
  // Downstream consumer applies its own sampling strategy while preserving causal provenance.
  await tracer.startActiveSpan(
    'process_order_event',
    {
      kind: SpanKind.CONSUMER,
      links,
      attributes: {
        'messaging.destination': msg.fields.routingKey
      }
    },
    ROOT_CONTEXT,
    async (span) => {
      try {
        await processMessagePayload(msg.content);
        span.setStatus({ code: 1 }); // OK
      } catch (err) {
        span.recordException(err as Error);
        span.setStatus({ code: 2, message: (err as Error).message });
        throw err;
      } finally {
        span.end();
      }
    }
  );
}
```

Recommended Agent Skills (askills.dev)

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

Architectural Specification & Invariant Rationale

Architectural Invariant Design: OpenTelemetry W3C Span Link Invariant for Decoupled Asynchronous Saga Tracing

OpenTelemetry W3C Span Link Invariant for Decoupled Asynchronous Saga Tracing defines an industrial-grade behavioral standard for devops engineering. Enforces causal trace lineage decoupling in asynchronous sagas by mandating OpenTelemetry W3C span links over direct parent-child span propagation. This prevents runaway trace cascades and downstream APM storage quota exhaustion while preserving distributed provenance across message brokers. 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: Direct Child Span Inheritance Across Asynchronous Message Boundaries Causing APM Quota Blowout 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 DriftDirect Child Span Inheritance Across Asynchronous Message Boundaries Causing APM Quota BlowoutCritical
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 upstream trace context using `propagation.extract(ROOT_CONTEXT, carrier)` to access the producer's SpanContext.

Engineers MUST ALWAYS extract upstream trace context using `propagation.extract(ROOT_CONTEXT, carrier)` to access the producer's SpanContext.

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 message SpanContext directly to `context.with()` or set it as the parent context of consumer processing spans.

Engineers MUST NOT pass an extracted message SpanContext directly to `context.with()` or set it as the parent context of consumer 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.
3

Services MUST instantiate consumer processing spans as new root spans (or children of the consumer framework context) explicitly attaching the extracted SpanContext via the `links` option

Services MUST instantiate consumer processing spans as new root spans (or children of the consumer framework context) explicitly attaching the extracted SpanContext via the `links` option: `links: [{ context: extractedSpanContext }]`.

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

Engineers MUST ensure consumer spans evaluate their own local sampling rules rather than blindly inheriting upstream sampled flags that blow APM storage quotas.

Engineers MUST ensure consumer spans evaluate their own local sampling rules rather than blindly inheriting upstream sampled flags that blow APM storage quotas.

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

Code SHOULD enrich the Span Link with semantic messaging attributes such as `messaging.operation

Code SHOULD enrich the Span Link with semantic messaging attributes such as `messaging.operation: 'process'` and `messaging.system` to preserve causal relationship intent.

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.
6

Components NEVER drop upstream W3C headers (`traceparent`, `tracestate`)

Components NEVER drop upstream W3C headers (`traceparent`, `tracestate`); they must be parsed into Span Links even if the consumer span itself is non-sampled.

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 W3C Span Link Invariant for Decoupled Asynchronous Saga Tracing critical for AI coding assistants?

Enforces causal trace lineage decoupling in asynchronous sagas by mandating OpenTelemetry W3C span links over direct parent-child span propagation. This prevents runaway trace cascades and downstream APM storage quota exhaustion while preserving distributed provenance across message brokers. 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 (Direct Child Span Inheritance Across Asynchronous Message Boundaries Causing APM Quota Blowout) 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