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

Axum 0.8 Tokio CancellationToken Propagation and Graceful Drain Invariant

Enforces cooperative async task cancellation and deterministic connection draining across Axum 0.8 routes, Tower middleware layers, and spawned Tokio background workers. Guarantees zero dropped in-flight transactions or truncated TCP frames during Kubernetes SIGTERM rolling terminations.

Prohibited Anti-Pattern: Detached Background Tasks and Naked Graceful Signals Causing In-Flight Transaction Truncation on SIGTERM

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Axum 0.8 Tokio CancellationToken Propagation and Graceful Drain Invariant - Enforces cooperative async task cancellation and deterministic connection draining across Axum 0.8 routes, Tower middleware layers, and spawned Tokio background workers. Guarantees zero dropped in-flight transactions or truncated TCP frames during Kubernetes SIGTERM rolling terminations.
globs: src/**/*.rs
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/axum-tokio-cancellation-token-graceful-drain"
---

# Axum 0.8 Tokio CancellationToken Propagation and Graceful Drain Invariant

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Detached Background Tasks and Naked Graceful Signals Causing In-Flight Transaction Truncation on SIGTERM

## System Constraints
You are a Principal Systems Architect enforcing the Axum 0.8 Tokio CancellationToken Propagation and Graceful Drain Invariant. All Axum servers running in containerized environments must achieve deterministic graceful draining. You must strictly forbid detached `tokio::spawn` tasks that lack cooperative cancellation hooks and tracker registration. Mandate the use of `tokio_util::sync::CancellationToken` and `tokio_util::task::TaskTracker` across the entire application lifecycle, binding OS signals (SIGTERM and SIGINT) to child tokens exposed via Axum Application State. Ensure that `axum::serve` is paired with both HTTP connection draining and asynchronous task synchronization before main runtime exit.

## Strict Guidelines
- Engineers MUST ALWAYS pair `axum::serve` graceful shutdown with `tokio_util::task::TaskTracker` and `tokio_util::sync::CancellationToken`.
- Engineers MUST NEVER invoke bare `tokio::spawn` for long-running or stateful side-effects; all background tasks MUST be spawned through `tracker.spawn(...)` with an attached child `CancellationToken`.
- Handlers spawning background workflows MUST extract `AppState` containing the `TaskTracker` and `CancellationToken` and periodically await `token.cancelled()` in loops or long I/O operations.
- Services MUST capture both `SIGTERM` (Kubernetes termination) and `SIGINT` (local interrupt) concurrently using `tokio::signal` multiplexing.
- Shutdown sequences MUST first notify `CancellationToken::cancel()`, await `axum::serve(...).with_graceful_shutdown(...)` completion, close the `TaskTracker`, and finally await `tracker.wait()` before process termination.
- Components NEVER call `std::process::exit` directly from signal handlers or Tower layers, as this bypasses RAII cleanup, non-flushed buffered writers, and DB connection pool release.

## Bad vs Good Implementations
### Graceful Drain and CancellationToken Propagation in Axum 0.8

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The implementation only handles basic ctrl_c, misses Unix SIGTERM, leaves background tasks detached without cancellation awareness, and exits main as soon as axum::serve stops listening, killing background workers mid-execution.
```rust
use axum::{routing::post, Router};
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/process", post(handle_task));
    let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();

    // ANTI-PATTERN: Naked shutdown signal; detached tasks are dropped immediately
    // when main exits, truncating work and causing HTTP 502s in Kubernetes.
    axum::serve(listener, app)
        .with_graceful_shutdown(async {
            tokio::signal::ctrl_c().await.ok();
        })
        .await
        .unwrap();
}

async fn handle_task() -> &'static str {
    // Detached task leaks on SIGTERM
    tokio::spawn(async {
        tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
        println!("Task done");
    });
    "Accepted"
}
```

#### Production Standard (Correct)
> **Standard**: Propagates a shared TaskTracker and hierarchical CancellationToken through Axum 0.8 State. Handles both SIGTERM and SIGINT, initiates server drain, and explicitly blocks process exit until all background tasks cooperatively finish or safely unwind.
```rust
use axum::{extract::State, routing::post, Router};
use std::sync::Arc;
use tokio::net::TcpListener;
use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;

#[derive(Clone)]
pub struct AppState {
    pub tracker: TaskTracker,
    pub cancel_token: CancellationToken,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let tracker = TaskTracker::new();
    let cancel_token = CancellationToken::new();
    let state = AppState {
        tracker: tracker.clone(),
        cancel_token: cancel_token.clone(),
    };

    let app = Router::new()
        .route("/process", post(handle_task))
        .with_state(Arc::new(state));

    let listener = TcpListener::bind("0.0.0.0:3000").await?;
    let root_token = cancel_token.clone();

    // Listen for OS SIGTERM and SIGINT
    tokio::spawn(async move {
        let ctrl_c = tokio::signal::ctrl_c();
        #[cfg(unix)]
        let mut sigterm = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
            .expect("Failed to install SIGTERM handler");

        #[cfg(unix)]
        tokio::select! {
            _ = ctrl_c => root_token.cancel(),
            _ = sigterm.recv() => root_token.cancel(),
        }

        #[cfg(not(unix))]
        tokio::select! {
            _ = ctrl_c => root_token.cancel(),
        }
    });

    let shutdown_token = cancel_token.clone();
    axum::serve(listener, app)
        .with_graceful_shutdown(async move {
            shutdown_token.cancelled().await;
        })
        .await?;

    // Close tracker and wait for cooperative drain of all background tasks
    tracker.close();
    tracker.wait().await;

    Ok(())
}

async fn handle_task(State(state): State<Arc<AppState>>) -> &'static str {
    let child_token = state.cancel_token.child_token();
    state.tracker.spawn(async move {
        tokio::select! {
            _ = child_token.cancelled() => {
                // Cooperative rollback or flush state here
            }
            _ = tokio::time::sleep(tokio::time::Duration::from_secs(10)) => {
                // Successful execution
            }
        }
    });
    "Accepted"
}
```

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 CancellationToken Propagation and Graceful Drain Invariant

Axum 0.8 Tokio CancellationToken Propagation and Graceful Drain Invariant defines an industrial-grade behavioral standard for backend engineering. Enforces cooperative async task cancellation and deterministic connection draining across Axum 0.8 routes, Tower middleware layers, and spawned Tokio background workers. Guarantees zero dropped in-flight transactions or truncated TCP frames during Kubernetes SIGTERM rolling terminations. 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: Detached Background Tasks and Naked Graceful Signals Causing In-Flight Transaction Truncation on SIGTERM 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 DriftDetached Background Tasks and Naked Graceful Signals Causing In-Flight Transaction Truncation on SIGTERMCritical
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 pair `axum

Engineers MUST ALWAYS pair `axum::serve` graceful shutdown with `tokio_util::task::TaskTracker` and `tokio_util::sync::CancellationToken`.

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 invoke bare `tokio

Engineers MUST NEVER invoke bare `tokio::spawn` for long-running or stateful side-effects; all background tasks MUST be spawned through `tracker.spawn(...)` with an attached child `CancellationToken`.

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

Handlers spawning background workflows MUST extract `AppState` containing the `TaskTracker` and `CancellationToken` and periodically await `token.cancelled()` in loops or long I/O operations.

Handlers spawning background workflows MUST extract `AppState` containing the `TaskTracker` and `CancellationToken` and periodically await `token.cancelled()` in loops or long I/O operations.

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 capture both `SIGTERM` (Kubernetes termination) and `SIGINT` (local interrupt) concurrently using `tokio

Services MUST capture both `SIGTERM` (Kubernetes termination) and `SIGINT` (local interrupt) concurrently using `tokio::signal` multiplexing.

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

Shutdown sequences MUST first notify `CancellationToken

Shutdown sequences MUST first notify `CancellationToken::cancel()`, await `axum::serve(...).with_graceful_shutdown(...)` completion, close the `TaskTracker`, and finally await `tracker.wait()` before process termination.

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 call `std

Components NEVER call `std::process::exit` directly from signal handlers or Tower layers, as this bypasses RAII cleanup, non-flushed buffered writers, and DB connection pool release.

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 CancellationToken Propagation and Graceful Drain Invariant critical for AI coding assistants?

Enforces cooperative async task cancellation and deterministic connection draining across Axum 0.8 routes, Tower middleware layers, and spawned Tokio background workers. Guarantees zero dropped in-flight transactions or truncated TCP frames during Kubernetes SIGTERM rolling terminations. 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 (Detached Background Tasks and Naked Graceful Signals Causing In-Flight Transaction Truncation on SIGTERM) 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