rust 45 lines · 8 steps

Graceful shutdown in an Axum server

Wire an Axum server to drain connections cleanly when it receives Ctrl+C or SIGTERM.

Explained by highlit
1use std::time::Duration;
2 
3use axum::{routing::get, Router};
4use tokio::net::TcpListener;
5use tokio::signal;
6 
7async fn shutdown_signal() {
8 let ctrl_c = async {
9 signal::ctrl_c()
10 .await
11 .expect("failed to install Ctrl+C handler");
12 };
13 
14 #[cfg(unix)]
15 let terminate = async {
16 signal::unix::signal(signal::unix::SignalKind::terminate())
17 .expect("failed to install SIGTERM handler")
18 .recv()
19 .await;
20 };
21 
22 #[cfg(not(unix))]
23 let terminate = std::future::pending::<()>();
24 
25 tokio::select! {
26 _ = ctrl_c => {},
27 _ = terminate => {},
28 }
29 
30 tracing::info!("shutdown signal received, draining connections");
31}
32 
33pub async fn serve() -> anyhow::Result<()> {
34 let app = Router::new().route("/health", get(|| async { "ok" }));
35 
36 let listener = TcpListener::bind("0.0.0.0:3000").await?;
37 tracing::info!("listening on {}", listener.local_addr()?);
38 
39 axum::serve(listener, app)
40 .with_graceful_shutdown(shutdown_signal())
41 .await?;
42 
43 tokio::time::sleep(Duration::from_millis(250)).await;
44 Ok(())
45}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Graceful shutdown means racing two signal futures and stopping the server when either fires.
  2. 2Platform differences like SIGTERM are handled with cfg attributes so the code compiles everywhere.
  3. 3with_graceful_shutdown lets Axum finish in-flight requests instead of dropping connections abruptly.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Graceful shutdown in an Axum server — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code