This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: axum-08-tower-backpressure-stream-throttling

Axum 0.8 Layered Tower Backpressure Stream Throttling

Enforces deterministic backpressure propagation across Axum 0.8 routing pipelines and Tower middleware layers down to underlying network sockets. Mandates strictly bounded channel buffering and frame consumption via http-body 1.0 to eliminate unbounded heap growth during slow-consumer and slow-read attacks.

Prohibited Anti-Pattern: Eager Buffering and Unbounded Asynchronous Queues in Streaming Tower Layers

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Axum 0.8 Layered Tower Backpressure Stream Throttling - Enforces deterministic backpressure propagation across Axum 0.8 routing pipelines and Tower middleware layers down to underlying network sockets. Mandates strictly bounded channel buffering and frame consumption via http-body 1.0 to eliminate unbounded heap growth during slow-consumer and slow-read attacks.
globs: src/**/*.rs, Cargo.toml
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/axum-08-tower-backpressure-stream-throttling"
---

# Axum 0.8 Layered Tower Backpressure Stream Throttling

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Eager Buffering and Unbounded Asynchronous Queues in Streaming Tower Layers

## System Constraints
You are a Principal Rust Architect enforcing Axum 0.8 Layered Tower Backpressure Stream Throttling. Mandate strict end-to-end backpressure propagation through all Tower middleware, stream extractors, and response bodies. Forbid unbounded in-memory collection (`to_bytes` with unlimited bounds), unbounded Tokio channels, and disconnected background streaming loops that decouple TCP flow control from application throughput.

## Strict Guidelines
- Engineers MUST ALWAYS enforce strict payload limits via `http_body_util::Limited` or Axum's `DefaultBodyLimit` before processing incoming stream frames.
- Engineers MUST NOT spawn detached tasks with unbounded channels (`tokio::sync::mpsc::unbounded_channel`) to process or bridge request and response stream bodies.
- Code SHOULD propagate backpressure directly through `http_body::Body::poll_frame` or bounded asynchronous channels using `reserve().await` or `send().await` to throttle upstream TCP reads when downstream sinks are saturated.
- Services MUST configure Tower middleware to respect `tower::Service::poll_ready` contracts and yield capacity only when downstream consumers are ready to receive data.
- Components NEVER collect streaming bodies into intermediate heap structures like `Vec<u8>` or `BytesMut` without an explicitly enforced ceiling and active flow control.

## Bad vs Good Implementations
### Streaming Request Body with Bounded Backpressure vs Unbounded Channel Buffering

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using an unbounded channel (`mpsc::unbounded_channel`) completely severs backpressure between the downstream consumer and the upstream socket. The producer task drains TCP buffers as fast as the network allows, buffering unbounded chunks in RAM and leading to heap exhaustion under slow-consumer attacks.
```rust
use axum::{body::Body, extract::Request, response::Response};
use tokio::sync::mpsc;
use http_body_util::BodyExt;

pub async fn leak_prone_stream_handler(req: Request) -> Response {
    // ANTI-PATTERN: Unbounded channel decouples TCP window from consumer speed.
    // A slow consumer causes unbounded memory allocation until OOM.
    let (tx, mut rx) = mpsc::unbounded_channel();
    let mut body = req.into_body();

    tokio::spawn(async move {
        while let Some(Ok(frame)) = body.frame().await {
            if let Some(chunk) = frame.data_ref() {
                let _ = tx.send(chunk.clone()); // Continues draining socket without backpressure
            }
        }
    });

    // Simulated slow consumer
    tokio::spawn(async move {
        while let Some(_data) = rx.recv().await {
            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
        }
    });

    Response::new(Body::empty())
}
```

#### Production Standard (Correct)
> **Standard**: Enforces dual protection: a size ceiling via `http_body_util::Limited` prevents unbounded payload attacks, while a bounded Tokio channel (`mpsc::channel(4)`) ensures `.send().await` halts the streaming loop when full, pausing socket polling and propagating backpressure through the TCP window.
```rust
use axum::{body::Body, extract::Request, http::StatusCode, response::{IntoResponse, Response}};
use http_body_util::{BodyExt, Limited};
use tokio::sync::mpsc;

const MAX_ALLOWED_PAYLOAD_BYTES: usize = 16 * 1024 * 1024; // 16 MiB hard limit
const BACKPRESSURE_BOUND: usize = 4; // Max 4 chunks inflight

pub async fn resilient_stream_handler(req: Request) -> Result<Response, StatusCode> {
    // INVARIANT 1: Bound total stream size to defeat memory exhaustion
    let limited_body = Limited::new(req.into_body(), MAX_ALLOWED_PAYLOAD_BYTES);
    let (tx, mut rx) = mpsc::channel(BACKPRESSURE_BOUND);
    let mut stream = limited_body.into_data_stream();

    // INVARIANT 2: Bounded channel enforces flow control on the producer
    tokio::spawn(async move {
        use futures_util::StreamExt;
        while let Some(chunk_result) = stream.next().await {
            match chunk_result {
                Ok(bytes) => {
                    // Permits wait when the buffer is full, pausing stream.next() and halting TCP reads
                    if tx.send(bytes).await.is_err() {
                        break; // Receiver dropped; cease pulling from socket immediately
                    }
                }
                Err(_) => break,
            }
        }
    });

    // Slow consumer now applies backpressure up to the TCP window
    tokio::spawn(async move {
        while let Some(_bytes) = rx.recv().await {
            tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
        }
    });

    Ok(StatusCode::ACCEPTED.into_response())
}
```

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 Layered Tower Backpressure Stream Throttling

Axum 0.8 Layered Tower Backpressure Stream Throttling defines an industrial-grade behavioral standard for backend engineering. Enforces deterministic backpressure propagation across Axum 0.8 routing pipelines and Tower middleware layers down to underlying network sockets. Mandates strictly bounded channel buffering and frame consumption via http-body 1.0 to eliminate unbounded heap growth during slow-consumer and slow-read attacks. 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: Eager Buffering and Unbounded Asynchronous Queues in Streaming Tower Layers 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 DriftEager Buffering and Unbounded Asynchronous Queues in Streaming Tower LayersCritical
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 enforce strict payload limits via `http_body_util

Engineers MUST ALWAYS enforce strict payload limits via `http_body_util::Limited` or Axum's `DefaultBodyLimit` before processing incoming stream frames.

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 spawn detached tasks with unbounded channels (`tokio

Engineers MUST NOT spawn detached tasks with unbounded channels (`tokio::sync::mpsc::unbounded_channel`) to process or bridge request and response stream bodies.

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 propagate backpressure directly through `http_body

Code SHOULD propagate backpressure directly through `http_body::Body::poll_frame` or bounded asynchronous channels using `reserve().await` or `send().await` to throttle upstream TCP reads when downstream sinks are saturated.

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 configure Tower middleware to respect `tower

Services MUST configure Tower middleware to respect `tower::Service::poll_ready` contracts and yield capacity only when downstream consumers are ready to receive data.

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 collect streaming bodies into intermediate heap structures like `Vec<u8>` or `BytesMut` without an explicitly enforced ceiling and active flow control.

Components NEVER collect streaming bodies into intermediate heap structures like `Vec<u8>` or `BytesMut` without an explicitly enforced ceiling and active flow control.

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 Layered Tower Backpressure Stream Throttling critical for AI coding assistants?

Enforces deterministic backpressure propagation across Axum 0.8 routing pipelines and Tower middleware layers down to underlying network sockets. Mandates strictly bounded channel buffering and frame consumption via http-body 1.0 to eliminate unbounded heap growth during slow-consumer and slow-read attacks. 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 (Eager Buffering and Unbounded Asynchronous Queues in Streaming Tower Layers) 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