Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Errors, Cancellation, and Backpressure

Axum distinguishes failures that are valid HTTP outcomes from failures that would otherwise escape the service.

Rejections are responses

Missing path data, invalid JSON, and absent headers are expected request failures. An extractor returns its rejection, and the handler adapter converts it with IntoResponse. The handler is never called.

Application errors follow the same model when their error type implements IntoResponse:

async fn handler() -> Result<Json<User>, ApiError> { /* ... */ }

This does not mean every internal error should be exposed. ApiError is the policy boundary that logs private context and chooses a safe status and body.

Tower errors must be handled before serving

Axum’s top-level router has Error = Infallible, because Hyper needs every request outcome to become a response. Middleware such as a generic Tower timeout may produce an error. HandleErrorLayer maps that error asynchronously to an IntoResponse, restoring the infallible outer contract.

Source: error_handling/mod.rs:115

Cancellation is usually dropping a future

If the peer disconnects and Hyper no longer needs the response, the request future may be dropped. Rust runs destructors for values currently owned by that future, but it does not roll back external effects.

  • a database transaction guard can roll back on drop;
  • a spawned child task may continue unless explicitly cancelled;
  • an already-sent email or payment cannot be unsent;
  • a multi-step mutation needs idempotency or a durable workflow boundary.

Cancellation safety is a property of each awaited operation, not a blanket guarantee supplied by Axum.

Readiness is deliberately subtle

Routing needs the request before it knows the destination. Axum therefore keeps routers always ready and drives destination readiness inside the returned future. A backpressure-sensitive service should be wrapped with an explicit load-shed, buffer, or limit policy—or placed around the entire router.

Source: middleware documentation

Graceful shutdown is a drain protocol

On shutdown, the server stops accepting new connections and signals connection tasks to begin Hyper’s graceful shutdown. A Tokio watch channel also accounts for live connection tasks. The server waits until their receivers are dropped.

Graceful does not imply bounded. A handler awaiting forever prevents complete drain, so production applications pair graceful shutdown with request or drain deadlines.

Source: serve/mod.rs:450