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

Axum 0.8 Tokio Select Cancellation-Safe State Standard

Enforces strict cancellation safety in Axum 0.8 asynchronous handlers using tokio::select! or timeout wrappers. Prevents dangling database transactions, orphaned resource handles, and half-consumed stream states caused by unpinned or non-cancellation-safe futures being dropped upon abrupt HTTP/3 client disconnection or socket termination.

Prohibited Anti-Pattern: Dropping Non-Cancellation-Safe Futures in tokio::select! Branches During Client Disconnects

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Axum 0.8 Tokio Select Cancellation-Safe State Standard - Enforces strict cancellation safety in Axum 0.8 asynchronous handlers using tokio::select! or timeout wrappers. Prevents dangling database transactions, orphaned resource handles, and half-consumed stream states caused by unpinned or non-cancellation-safe futures being dropped upon abrupt HTTP/3 client disconnection or socket termination.
globs: src/**/*.rs
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/axum-08-tokio-select-cancellation-safe-state-standard"
---

# Axum 0.8 Tokio Select Cancellation-Safe State Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Dropping Non-Cancellation-Safe Futures in tokio::select! Branches During Client Disconnects

## System Constraints
You are a Principal Rust Systems Architect enforcing strict cancellation safety across Axum 0.8 and Tokio runtimes. You must prevent partial transactional commits, corrupted streaming states, and resource leaks caused by dropping futures in `tokio::select!` branches or client disconnect abort paths. Ensure every multi-stage operation, database mutation, or stream consumption across HTTP/3 request lifecycles maintains atomic invariants through explicit rollback guards, background detachment via `tokio::spawn`, or verified cancellation-safe futures.

## Strict Guidelines
- Engineers MUST NEVER invoke non-cancellation-safe futures (such as `AsyncWriteExt::write_all`, `sqlx::Transaction::commit`, or multi-step message reads) inside a `tokio::select!` branch without atomic guards or loop state reconciliation.
- Engineers MUST wrap stateful database mutations in an explicit RAII rollback guard or move the transactional boundary entirely into a detached `tokio::spawn` task when execution must run to completion irrespective of client connection teardown.
- Engineers MUST ensure that any future passed by reference to `tokio::select!` is explicitly pinned using `tokio::pin!` across loop iterations to preserve state across select branch cancellations.
- Handlers MUST NOT rely on synchronous drop implementations alone to commit critical business transactions, as client disconnects in HTTP/3 immediately abort handler futures at the first `.await` yield point.
- Engineers SHOULD leverage `tokio_util::sync::CancellationToken` or dedicated background channels to signal graceful shutdown and rollbacks rather than allowing raw socket drops to abruptly sever pipeline states.

## Bad vs Good Implementations
### Cancellation-unsafe Transaction in tokio::select! Branch

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: When an HTTP/3 client abruptly resets the stream or times out, Axum drops the handler future at the nearest yield point. In the bad example, dropping the inner async block leaves intermediate transactional operations unmanaged in flight and abandons the commit sequence mid-stream, relying solely on runtime drop semantics that can block connection reuse or result in lost mutation intents.
```rust
use axum::{extract::State, http::StatusCode, response::IntoResponse};
use sqlx::PgPool;
use tokio::time::{sleep, Duration};

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

    // ANTI-PATTERN: If client disconnects or timeout branch triggers while
    // processing, the mutation future is dropped. Partial writes may persist
    // until pool rollback, or intermediary socket writes leak halfway.
    tokio::select! {
        _ = sleep(Duration::from_secs(5)) => {
            Err(StatusCode::REQUEST_TIMEOUT)
        }
        res = async {
            sqlx::query("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
                .execute(&mut *tx)
                .await?;
            // Non-cancellation safe: if cancelled right here, balance is reduced but order is never recorded
            sqlx::query("INSERT INTO orders (user_id, amount) VALUES (1, 100)")
                .execute(&mut *tx)
                .await?;
            tx.commit().await
        } => {
            res.map(|_| StatusCode::OK).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}
```

#### Production Standard (Correct)
> **Standard**: Decouples the transactional boundary from the transient HTTP connection lifecycle. If the HTTP/3 stream is aborted or dropped, the detached `tokio::spawn` worker continues to completion or executes an explicit database rollback, eliminating partial updates and resource leaks.
```rust
use axum::{extract::State, http::StatusCode, response::IntoResponse};
use sqlx::PgPool;
use tokio::sync::oneshot;

pub async fn handle_order_checkout(
    State(pool): State<PgPool>,
) -> Result<impl IntoResponse, StatusCode> {
    let (tx_done, rx_done) = oneshot::channel();

    // PRODUCTION FIX: Critical transactional operations are spawned to run to completion.
    // Disconnection of the HTTP handler drops the receiver, NOT the running transaction.
    tokio::spawn(async move {
        let result = async {
            let mut tx = pool.begin().await?;
            sqlx::query("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
                .execute(&mut *tx)
                .await?;
            sqlx::query("INSERT INTO orders (user_id, amount) VALUES (1, 100)")
                .execute(&mut *tx)
                .await?;
            tx.commit().await?;
            Ok::<(), sqlx::Error>(())
        }.await;

        let _ = tx_done.send(result);
    });

    match rx_done.await {
        Ok(Ok(())) => Ok(StatusCode::OK),
        Ok(Err(_)) => Err(StatusCode::INTERNAL_SERVER_ERROR),
        Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), // Task panicked or aborted cleanly
    }
}
```

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 Select Cancellation-Safe State Standard

Axum 0.8 Tokio Select Cancellation-Safe State Standard defines an industrial-grade behavioral standard for backend engineering. Enforces strict cancellation safety in Axum 0.8 asynchronous handlers using tokio::select! or timeout wrappers. Prevents dangling database transactions, orphaned resource handles, and half-consumed stream states caused by unpinned or non-cancellation-safe futures being dropped upon abrupt HTTP/3 client disconnection or socket termination. 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: Dropping Non-Cancellation-Safe Futures in tokio::select! Branches During Client Disconnects 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 DriftDropping Non-Cancellation-Safe Futures in tokio::select! Branches During Client DisconnectsCritical
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 NEVER invoke non-cancellation-safe futures (such as `AsyncWriteExt

Engineers MUST NEVER invoke non-cancellation-safe futures (such as `AsyncWriteExt::write_all`, `sqlx::Transaction::commit`, or multi-step message reads) inside a `tokio::select!` branch without atomic guards or loop state reconciliation.

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 wrap stateful database mutations in an explicit RAII rollback guard or move the transactional boundary entirely into a detached `tokio

Engineers MUST wrap stateful database mutations in an explicit RAII rollback guard or move the transactional boundary entirely into a detached `tokio::spawn` task when execution must run to completion irrespective of client connection teardown.

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

Engineers MUST ensure that any future passed by reference to `tokio

Engineers MUST ensure that any future passed by reference to `tokio::select!` is explicitly pinned using `tokio::pin!` across loop iterations to preserve state across select branch cancellations.

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

Handlers MUST NOT rely on synchronous drop implementations alone to commit critical business transactions, as client disconnects in HTTP/3 immediately abort handler futures at the first `.await` yield point.

Handlers MUST NOT rely on synchronous drop implementations alone to commit critical business transactions, as client disconnects in HTTP/3 immediately abort handler futures at the first `.await` yield point.

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 SHOULD leverage `tokio_util

Engineers SHOULD leverage `tokio_util::sync::CancellationToken` or dedicated background channels to signal graceful shutdown and rollbacks rather than allowing raw socket drops to abruptly sever pipeline states.

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 Select Cancellation-Safe State Standard critical for AI coding assistants?

Enforces strict cancellation safety in Axum 0.8 asynchronous handlers using tokio::select! or timeout wrappers. Prevents dangling database transactions, orphaned resource handles, and half-consumed stream states caused by unpinned or non-cancellation-safe futures being dropped upon abrupt HTTP/3 client disconnection or socket termination. 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 (Dropping Non-Cancellation-Safe Futures in tokio::select! Branches During Client Disconnects) 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