This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: axum-cancel-safe-stream-drop-guardrail

Axum 0.8 Cancel-Safe Async Pipeline and HTTP/3 Stream Drop Guardrail

Enforces cancellation-safe async state machines, atomic transaction boundaries, and Tokio CancellationToken propagation across Axum 0.8 middleware and handlers. Prevents dangling database mutations, orphaned remote RPC side effects, and resource leaks when HTTP/3 QUIC client streams terminate or reset prematurely mid-flight.

Prohibited Anti-Pattern: Non-Cancel-Safe Multi-Stage Awaits Yielding Orphaned Mutations on HTTP/3 Stream Reset

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Axum 0.8 Cancel-Safe Async Pipeline and HTTP/3 Stream Drop Guardrail - Enforces cancellation-safe async state machines, atomic transaction boundaries, and Tokio CancellationToken propagation across Axum 0.8 middleware and handlers. Prevents dangling database mutations, orphaned remote RPC side effects, and resource leaks when HTTP/3 QUIC client streams terminate or reset prematurely mid-flight.
globs: src/**/*.rs, crates/**/*.rs
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/axum-cancel-safe-stream-drop-guardrail"
---

# Axum 0.8 Cancel-Safe Async Pipeline and HTTP/3 Stream Drop Guardrail

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Non-Cancel-Safe Multi-Stage Awaits Yielding Orphaned Mutations on HTTP/3 Stream Reset

## System Constraints
You are a Principal Systems Architect enforcing cancel-safe async invariants in Rust and Axum 0.8 under HTTP/3 (QUIC) and HTTP/2 transport semantics. In HTTP/3, stream resets (RST_STREAM) and connection aborts immediately drop Axum handler futures at any `.await` boundary. You must ensure that asynchronous handlers never leave database records in partial states, never invoke remote mutations without compensatory transactions or idempotency keys, and rigorously employ RAII drop guards and `tokio_util::sync::CancellationToken` for operations that cannot be safely cancelled mid-stream.

## Strict Guidelines
- Engineers MUST ALWAYS encapsulate multi-step state mutations within atomic database transactions (`sqlx::Transaction` or equivalent) where drop-semantics default to an immediate `ROLLBACK`.
- Engineers MUST NOT execute external remote side effects (e.g., payment gateways, email dispatch, webhook triggers) directly between uncommitted transactional `.await` points without an idempotent outbox pattern.
- Code SHOULD employ RAII Drop guards or `tokio::spawn` with explicit detached boundary markers when an async task must guarantee completion despite client disconnects.
- Services MUST propagate `tokio_util::sync::CancellationToken` through Axum request extensions to downstream background workers to signal graceful aborts on client stream drop.
- Components NEVER use non-cancel-safe primitives like `tokio::select!` branches holding uncommitted transaction states or shared locks across cancellable stream read boundaries.

## Bad vs Good Implementations
### Cancel-Unsafe Mutation Pipeline vs. Transactional RAII Outbox with Cancellation Token

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: In Axum under HTTP/3, stream drops instantly abort handler execution at the intermediate `.await` point. Executing standalone SQL updates and external RPC calls sequentially without an atomic transaction boundary or transactional outbox causes catastrophic data corruption and state desynchronization.
```rust
use axum::{extract::State, http::StatusCode, Json};
use sqlx::PgPool;
use serde::Deserialize;

#[derive(Deserialize)]
pub struct CreateOrder { pub user_id: i64, pub amount_cents: i64 }

// ANTI-PATTERN: If client drops the HTTP/3 stream during `charge_external`, 
// the future is dropped immediately. The balance debit remains committed, 
// but the order record is never created and inventory is never reserved.
pub async fn checkout_order(
    State(pool): State<PgPool>,
    Json(payload): Json<CreateOrder>,
) -> Result<StatusCode, StatusCode> {
    // Step 1: Debits user balance directly on the pool
    sqlx::query!("UPDATE balances SET cents = cents - $1 WHERE user_id = $2", payload.amount_cents, payload.user_id)
        .execute(&pool)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // Client resets QUIC stream right here -> Handler dropped, subsequent steps skipped!
    external_payment_client::charge_external(payload.user_id, payload.amount_cents)
        .await
        .map_err(|_| StatusCode::BAD_GATEWAY)?;

    // Step 3: Never runs
    sqlx::query!("INSERT INTO orders (user_id, cents) VALUES ($1, $2)", payload.user_id, payload.amount_cents)
        .execute(&pool)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    Ok(StatusCode::CREATED)
}
```

#### Production Standard (Correct)
> **Standard**: All state changes and external intent are bound to a single `sqlx::Transaction`. If the HTTP/3 stream terminates early, the Rust RAII drop implementation on `Transaction` aborts the connection, issuing an immediate ROLLBACK and leaving the database in a completely consistent state.
```rust
use axum::{extract::State, http::StatusCode, Json};
use sqlx::{PgPool, Postgres, Transaction};
use serde::Deserialize;
use tokio_util::sync::CancellationToken;
use uuid::Uuid;

#[derive(Deserialize)]
pub struct CreateOrder { pub user_id: i64, pub amount_cents: i64 }

// PRODUCTION FIX: Transaction drop guard guarantees automatic ROLLBACK on future cancellation.
// External side effects are staged via an atomic Outbox row, decoupling client stream lifecycle
// from mission-critical external execution.
pub async fn checkout_order(
    State(pool): State<PgPool>,
    Json(payload): Json<CreateOrder>,
) -> Result<StatusCode, StatusCode> {
    let idempotency_key = Uuid::now_v7();
    
    // RAII Transaction: If HTTP/3 stream resets anywhere before `.commit().await`,
    // `tx` is dropped and Postgres automatically rolls back the entire transaction.
    let mut tx: Transaction<'_, Postgres> = pool.begin()
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    sqlx::query!(
        "UPDATE balances SET cents = cents - $1 WHERE user_id = $2",
        payload.amount_cents,
        payload.user_id
    )
    .execute(&mut *tx)
    .await
    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    sqlx::query!(
        "INSERT INTO orders (id, user_id, cents) VALUES ($1, $2, $3)",
        idempotency_key,
        payload.user_id,
        payload.amount_cents
    )
    .execute(&mut *tx)
    .await
    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // Staged side-effect in Outbox table (safe against mid-flight stream reset)
    sqlx::query!(
        "INSERT INTO payment_outbox (idempotency_key, user_id, cents, status) VALUES ($1, $2, $3, 'pending')",
        idempotency_key,
        payload.user_id,
        payload.amount_cents
    )
    .execute(&mut *tx)
    .await
    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // Atomic commit boundary: only commits if client stream is still active
    tx.commit()
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    Ok(StatusCode::CREATED)
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Axum 0.8 Cancel-Safe Async Pipeline and HTTP/3 Stream Drop Guardrail

Axum 0.8 Cancel-Safe Async Pipeline and HTTP/3 Stream Drop Guardrail defines an industrial-grade behavioral standard for backend engineering. Enforces cancellation-safe async state machines, atomic transaction boundaries, and Tokio CancellationToken propagation across Axum 0.8 middleware and handlers. Prevents dangling database mutations, orphaned remote RPC side effects, and resource leaks when HTTP/3 QUIC client streams terminate or reset prematurely mid-flight. 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: Non-Cancel-Safe Multi-Stage Awaits Yielding Orphaned Mutations on HTTP/3 Stream Reset 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 DriftNon-Cancel-Safe Multi-Stage Awaits Yielding Orphaned Mutations on HTTP/3 Stream ResetCritical
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 encapsulate multi-step state mutations within atomic database transactions (`sqlx

Engineers MUST ALWAYS encapsulate multi-step state mutations within atomic database transactions (`sqlx::Transaction` or equivalent) where drop-semantics default to an immediate `ROLLBACK`.

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 execute external remote side effects (e.g., payment gateways, email dispatch, webhook triggers) directly between uncommitted transactional `.await` points without an idempotent outbox pattern.

Engineers MUST NOT execute external remote side effects (e.g., payment gateways, email dispatch, webhook triggers) directly between uncommitted transactional `.await` points without an idempotent outbox pattern.

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

Code SHOULD employ RAII Drop guards or `tokio

Code SHOULD employ RAII Drop guards or `tokio::spawn` with explicit detached boundary markers when an async task must guarantee completion despite client disconnects.

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

Services MUST propagate `tokio_util

Services MUST propagate `tokio_util::sync::CancellationToken` through Axum request extensions to downstream background workers to signal graceful aborts on client stream drop.

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

Components NEVER use non-cancel-safe primitives like `tokio

Components NEVER use non-cancel-safe primitives like `tokio::select!` branches holding uncommitted transaction states or shared locks across cancellable stream read boundaries.

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 Axum 0.8 Cancel-Safe Async Pipeline and HTTP/3 Stream Drop Guardrail critical for AI coding assistants?

Enforces cancellation-safe async state machines, atomic transaction boundaries, and Tokio CancellationToken propagation across Axum 0.8 middleware and handlers. Prevents dangling database mutations, orphaned remote RPC side effects, and resource leaks when HTTP/3 QUIC client streams terminate or reset prematurely mid-flight. 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 (Non-Cancel-Safe Multi-Stage Awaits Yielding Orphaned Mutations on HTTP/3 Stream Reset) 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

Axum