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

Axum 0.8 Tokio Cooperative Request Cancellation and Drop Safety Standard

Enforces strict cancellation safety, explicit drop semantics, and deterministic transaction rollbacks under Axum 0.8 and Tokio runtimes. When HTTP/2 clients terminate connections prematurely or reset streams (RST_STREAM), pending futures are dropped mid-execution, which can leave database connection pools depleted or lock states orphaned if asynchronous resources are not wrapped in drop guards or shielded spawn blocks.

Prohibited Anti-Pattern: Orphaned Transactions and Poisoned DB Pool Locks Due to Premature Stream Drops

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Axum 0.8 Tokio Cooperative Request Cancellation and Drop Safety Standard - Enforces strict cancellation safety, explicit drop semantics, and deterministic transaction rollbacks under Axum 0.8 and Tokio runtimes. When HTTP/2 clients terminate connections prematurely or reset streams (RST_STREAM), pending futures are dropped mid-execution, which can leave database connection pools depleted or lock states orphaned if asynchronous resources are not wrapped in drop guards or shielded spawn blocks.
globs: src/**/*.rs, crates/**/*.rs
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/axum-tokio-cancellation-cleanup-guardrail"
---

# Axum 0.8 Tokio Cooperative Request Cancellation and Drop Safety Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Orphaned Transactions and Poisoned DB Pool Locks Due to Premature Stream Drops

## System Constraints
You are a Principal Rust Systems Architect enforcing strict Tokio cooperative cancellation invariants in Axum 0.8 handlers. Premature client disconnects (HTTP/2 RST_STREAM, network drops) trigger instantaneous drops of Axum handler futures. You must reject any handler logic where multi-step non-idempotent operations, raw sqlx::Transaction handles, or external mutations rely on downstream code executing after a cancellation point without an explicit Drop guard, tokio::task::spawn isolation, or tokio::select! drop resilience.

## Strict Guidelines
- Engineers MUST ALWAYS isolate critical, non-cancellable database write sequences into detached tasks using `tokio::task::spawn` or background worker queues if they must complete regardless of client disconnection.
- Engineers MUST NEVER hold raw database locks or uncommitted manual transactions across unshielded cancellation points without relying on RAII drop-safe constructs (e.g., ensuring `sqlx::Transaction` explicitly triggers automatic rollback on Drop).
- Code MUST verify cancellation safety of all future branches inside `tokio::select!` loops to avoid partial state corruption or resource leakage when an alternate branch resolves first.
- Services MUST implement explicit custom Drop guards or utilize `tokio_util::sync::CancellationToken` when coordinating graceful tear-down across nested worker tasks upon parent stream cancellation.
- Engineers MUST NOT rely on cleanup code located sequentially after an `.await` point within an Axum request handler, as subsequent statements will never execute if the client drops the socket.

## Bad vs Good Implementations
### Handling Cancellation During Multi-Step Transactions

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: If the client disconnects while the external HTTP call is awaiting, the Axum request future is abruptly dropped. While sqlx::Transaction drops and issues a deferred rollback, the external charge succeeded, creating a catastrophic split-brain state between ledger and external provider because cleanup code after the await is unreachable.
```rust
use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
use sqlx::PgPool;
use serde::Deserialize;

#[derive(Deserialize)]
pub struct OrderPayload { pub user_id: i64, pub amount: i64 }

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

    // ANTI-PATTERN: Client disconnect here will drop the future immediately.
    // Subsequent cleanup or audit notifications are skipped, and multi-step external calls
    // leave uncommitted side effects in downstream services.
    sqlx::query!("UPDATE accounts SET balance = balance - $1 WHERE id = $2", payload.amount, payload.user_id)
        .execute(&mut *tx)
        .await
        .map_err(|_| StatusCode::BAD_REQUEST)?;

    // Emitting payment to external gateway; client cancellation mid-await drops handler,
    // leaving external gateway charged while DB tx is dropped (rolled back), causing desync.
    reqwest::Client::new()
        .post("https://payment.gateway.internal/charge")
        .json(&payload)
        .send()
        .await
        .map_err(|_| StatusCode::BAD_GATEWAY)?;

    tx.commit().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    Ok(StatusCode::CREATED)
}
```

#### Production Standard (Correct)
> **Standard**: By offloading the critical sequence into an isolated `tokio::spawn` task and evaluating cooperative cancellation checkpoints, the handler ensures execution consistency. Even if the Axum HTTP worker drops, the atomic transition is either completed or cleanly halted without leaving uncommitted side-effects or half-executed state transitions.
```rust
use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
use sqlx::PgPool;
use serde::Deserialize;
use tokio_util::sync::CancellationToken;

#[derive(Deserialize, Clone)]
pub struct OrderPayload { pub user_id: i64, pub amount: i64 }

pub async fn place_order(
    State(pool): State<PgPool>,
    Json(payload): Json<OrderPayload>,
) -> Result<impl IntoResponse, StatusCode> {
    let token = CancellationToken::new();
    let child_token = token.child_token();

    // INVARIANT FIX: Execute critical distributed write within detached task shielded
    // from abrupt Axum future drop semantics, coordinating via CancellationToken and RAII.
    let worker_handle = tokio::spawn(async move {
        let mut tx = pool.begin().await?;
        
        sqlx::query!("UPDATE accounts SET balance = balance - $1 WHERE id = $2", payload.amount, payload.user_id)
            .execute(&mut *tx)
            .await?;

        // Guard against premature cancellation before irreversible action
        if child_token.is_cancelled() {
            return Err(anyhow::anyhow!("Client aborted prior to charge"));
        }

        reqwest::Client::new()
            .post("https://payment.gateway.internal/charge")
            .json(&payload)
            .send()
            .await?
            .error_for_status()?;

        tx.commit().await?;
        Ok::<(), anyhow::Error>(())
    });

    match worker_handle.await {
        Ok(Ok(())) => Ok(StatusCode::CREATED),
        Ok(Err(_)) => Ok(StatusCode::UNPROCESSABLE_ENTITY),
        Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
    }
}
```

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: Axum 0.8 Tokio Cooperative Request Cancellation and Drop Safety Standard

Axum 0.8 Tokio Cooperative Request Cancellation and Drop Safety Standard defines an industrial-grade behavioral standard for backend engineering. Enforces strict cancellation safety, explicit drop semantics, and deterministic transaction rollbacks under Axum 0.8 and Tokio runtimes. When HTTP/2 clients terminate connections prematurely or reset streams (RST_STREAM), pending futures are dropped mid-execution, which can leave database connection pools depleted or lock states orphaned if asynchronous resources are not wrapped in drop guards or shielded spawn blocks. 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: Orphaned Transactions and Poisoned DB Pool Locks Due to Premature Stream Drops 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 DriftOrphaned Transactions and Poisoned DB Pool Locks Due to Premature Stream DropsCritical
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 isolate critical, non-cancellable database write sequences into detached tasks using `tokio

Engineers MUST ALWAYS isolate critical, non-cancellable database write sequences into detached tasks using `tokio::task::spawn` or background worker queues if they must complete regardless of 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.
2

Engineers MUST NEVER hold raw database locks or uncommitted manual transactions across unshielded cancellation points without relying on RAII drop-safe constructs (e.g., ensuring `sqlx

Engineers MUST NEVER hold raw database locks or uncommitted manual transactions across unshielded cancellation points without relying on RAII drop-safe constructs (e.g., ensuring `sqlx::Transaction` explicitly triggers automatic rollback on 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.
3

Code MUST verify cancellation safety of all future branches inside `tokio

Code MUST verify cancellation safety of all future branches inside `tokio::select!` loops to avoid partial state corruption or resource leakage when an alternate branch resolves first.

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 implement explicit custom Drop guards or utilize `tokio_util

Services MUST implement explicit custom Drop guards or utilize `tokio_util::sync::CancellationToken` when coordinating graceful tear-down across nested worker tasks upon parent stream cancellation.

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

Engineers MUST NOT rely on cleanup code located sequentially after an `.await` point within an Axum request handler, as subsequent statements will never execute if the client drops the socket.

Engineers MUST NOT rely on cleanup code located sequentially after an `.await` point within an Axum request handler, as subsequent statements will never execute if the client drops the socket.

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 Cooperative Request Cancellation and Drop Safety Standard critical for AI coding assistants?

Enforces strict cancellation safety, explicit drop semantics, and deterministic transaction rollbacks under Axum 0.8 and Tokio runtimes. When HTTP/2 clients terminate connections prematurely or reset streams (RST_STREAM), pending futures are dropped mid-execution, which can leave database connection pools depleted or lock states orphaned if asynchronous resources are not wrapped in drop guards or shielded spawn blocks. 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 (Orphaned Transactions and Poisoned DB Pool Locks Due to Premature Stream Drops) 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