This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: axum-tokio-task-local-cancellation-safety

Axum 0.8 Tokio Task-Local Extraction and Cancellation Safety Standard

Enforces strict drop-safety, RAII cleanup guarantees, and scoped Tokio task-local context propagation across nested Tower middleware and Axum 0.8 request pipelines. Prevents resource leaks, orphaned database transactions, and corrupted task-local states when client connections abort unexpectedly mid-flight.

Prohibited Anti-Pattern: Unprotected mutable state and non-RAII resource cleanup across cancellation points in Axum request pipelines

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Axum 0.8 Tokio Task-Local Extraction and Cancellation Safety Standard - Enforces strict drop-safety, RAII cleanup guarantees, and scoped Tokio task-local context propagation across nested Tower middleware and Axum 0.8 request pipelines. Prevents resource leaks, orphaned database transactions, and corrupted task-local states when client connections abort unexpectedly mid-flight.
globs: src/**/*.rs
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/axum-tokio-task-local-cancellation-safety"
---

# Axum 0.8 Tokio Task-Local Extraction and Cancellation Safety Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unprotected mutable state and non-RAII resource cleanup across cancellation points in Axum request pipelines

## System Constraints
You are a Principal Rust Architect enforcing the Axum 0.8 and Tokio Task-Local Extraction and Cancellation Safety Standard. Every Axum handler, Tower middleware layer, and Tokio task-local accessor must guarantee transactional rollback and resource reclamation under immediate future cancellation when HTTP connections abort.

## Strict Guidelines
- Engineers MUST ALWAYS wrap non-reentrant asynchronous workflows in RAII drop guards or use `tokio_util::sync::CancellationToken` to handle unexpected connection drops.
- Engineers MUST NOT rely on cleanup logic located strictly after an `.await` boundary in Axum handlers, as hyper drops handler futures instantaneously upon client disconnection.
- Code MUST propagate Tokio `task_local!` values explicitly across background task spawns using `task_local.scope(...)` rather than assuming ambient inheritance in `tokio::spawn`.
- Services MUST ensure database transactions or leased pool connections utilize an automatic rollback-on-drop guard instead of explicit manual rollback invocations.
- Middleware layers MUST implement Tower's `Service` trait with cancellation-safe `poll_ready` contracts and ensure request context scoping wraps the downstream `service.call(req)` future.

## Bad vs Good Implementations
### Cancellation-Unsafe Handler vs. RAII Drop-Safe Scoped Task Execution

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Client connection termination instantly drops the Axum handler future at any `.await` point. Unscoped task-local access in spawned tasks panics, and relying on sequential execution after await boundaries prevents reliable resource synchronization and metrics emission.
```rust
use axum::{extract::State, http::StatusCode, response::IntoResponse};
use tokio::task_local;

task_local! {
    pub static TRACE_ID: String;
}

pub async fn transfer_handler(
    State(pool): State<sqlx::PgPool>,
) -> Result<impl IntoResponse, StatusCode> {
    let mut tx = pool.begin().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // ANTI-PATTERN: If client disconnects during debit or credit, the future drops immediately.
    // Cleanup code after .await never executes, and detached spawn loses task-local trace context.
    sqlx::query("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
        .execute(&mut *tx)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // Untracked background task loses TRACE_ID task-local scope
    tokio::spawn(async move {
        // Panics: TRACE_ID not set in spawned task
        let _tid = TRACE_ID.get();
    });

    sqlx::query("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
        .execute(&mut *tx)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // Manual commit: if dropped before this point, transaction cleanup depends purely on pool drop heuristics
    tx.commit().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    Ok(StatusCode::OK)
}
```

#### Production Standard (Correct)
> **Standard**: Leverages sqlx's RAII drop semantics for automatic transaction rollback, scopes the task-local variable into spawned background routines explicitly via `TRACE_ID.scope(...)`, and utilizes a `CancellationToken` drop guard to propagate client aborts downstream.
```rust
use axum::{extract::State, http::StatusCode, response::IntoResponse};
use tokio::task_local;
use tokio_util::sync::CancellationToken;

task_local! {
    pub static TRACE_ID: String;
}

pub async fn transfer_handler(
    State(pool): State<sqlx::PgPool>,
) -> Result<impl IntoResponse, StatusCode> {
    let current_trace_id = TRACE_ID.with(|id| id.clone());
    let token = CancellationToken::new();
    let _drop_guard = token.clone().drop_guard();

    let mut tx = pool.begin().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // Spawning with cloned task-local scope and cancellation tracking
    let child_token = token.clone();
    let trace_for_spawn = current_trace_id.clone();
    tokio::spawn(
        TRACE_ID.scope(trace_for_spawn, async move {
            tokio::select! {
                _ = child_token.cancelled() => { /* Graceful background shutdown */ }
                _ = async { /* Non-critical audit processing */ } => {}
            }
        })
    );

    // sqlx::Transaction implements Drop with an implicit rollback on drop
    sqlx::query("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
        .execute(&mut *tx)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    sqlx::query("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
        .execute(&mut *tx)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    tx.commit().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    token.cancel(); // Normal completion disarms drop guard

    Ok(StatusCode::OK)
}
```

Recommended Agent Skills (askills.dev)

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

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Axum 0.8 Tokio Task-Local Extraction and Cancellation Safety Standard

Axum 0.8 Tokio Task-Local Extraction and Cancellation Safety Standard defines an industrial-grade behavioral standard for backend engineering. Enforces strict drop-safety, RAII cleanup guarantees, and scoped Tokio task-local context propagation across nested Tower middleware and Axum 0.8 request pipelines. Prevents resource leaks, orphaned database transactions, and corrupted task-local states when client connections abort unexpectedly 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: Unprotected mutable state and non-RAII resource cleanup across cancellation points in Axum request pipelines 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 DriftUnprotected mutable state and non-RAII resource cleanup across cancellation points in Axum request pipelinesCritical
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 wrap non-reentrant asynchronous workflows in RAII drop guards or use `tokio_util

Engineers MUST ALWAYS wrap non-reentrant asynchronous workflows in RAII drop guards or use `tokio_util::sync::CancellationToken` to handle unexpected connection drops.

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 rely on cleanup logic located strictly after an `.await` boundary in Axum handlers, as hyper drops handler futures instantaneously upon client disconnection.

Engineers MUST NOT rely on cleanup logic located strictly after an `.await` boundary in Axum handlers, as hyper drops handler futures instantaneously upon client disconnection.

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 MUST propagate Tokio `task_local!` values explicitly across background task spawns using `task_local.scope(...)` rather than assuming ambient inheritance in `tokio

Code MUST propagate Tokio `task_local!` values explicitly across background task spawns using `task_local.scope(...)` rather than assuming ambient inheritance in `tokio::spawn`.

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 ensure database transactions or leased pool connections utilize an automatic rollback-on-drop guard instead of explicit manual rollback invocations.

Services MUST ensure database transactions or leased pool connections utilize an automatic rollback-on-drop guard instead of explicit manual rollback invocations.

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

Middleware layers MUST implement Tower's `Service` trait with cancellation-safe `poll_ready` contracts and ensure request context scoping wraps the downstream `service.call(req)` future.

Middleware layers MUST implement Tower's `Service` trait with cancellation-safe `poll_ready` contracts and ensure request context scoping wraps the downstream `service.call(req)` future.

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 Tokio Task-Local Extraction and Cancellation Safety Standard critical for AI coding assistants?

Enforces strict drop-safety, RAII cleanup guarantees, and scoped Tokio task-local context propagation across nested Tower middleware and Axum 0.8 request pipelines. Prevents resource leaks, orphaned database transactions, and corrupted task-local states when client connections abort unexpectedly 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 (Unprotected mutable state and non-RAII resource cleanup across cancellation points in Axum request pipelines) 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