Gracefully Shutting Down A Rust Application
Gracefully Shutting Down A Rust Application
Gracefully Shutting Down A Rust Application

It's pretty common when developing a Rust application to restart the application by pressing "CTRL + C/CMD + C". Quick and easy. Get's the job done with minimal hustle. Now for the case that your Rust application is running in production, handling many requests at the same time, running database transactions and may be communicating with other web services etc. What would happen if you did that?

  • Users would get an abrupt "Service Unavailable" error.
  • some database commits would be lost.
  • some working web services would be thrown into disarray.
  • the worst, data corruption happening.

This is where graceful shudown of a Rust application comes in. By gracefully shutting down we ensure that any long running process or worker or incoming requests are gracefully handled/rejected before powering down. This prevents the nasty outcomes above. So, how do you do it in Rust?

I'll just use a simple Axum version but the best is to offer robust graceful shutdown for each OS architecture and also cycling through workers to power each one down prior to shutting down the application. Now, the code to send out our shutdown signal:

	
		async fn shutdown_signal() {
		    tokio::signal::ctrl_c()
		        .await
		        .expect("failed to install Ctrl+C handler");
		    info!("Received shutdown signal");
		}
	
	

Then in your main() function that serves the app you can do something like this:

	
		#[tokio::main]
		async fn main() {
		    ...

		    // Create application state
		    let app_state = AppState::new(tera, pool, appname);

		    // Build the router with session middleware
		    let app = create_router(app_state)
		        .layer(from_fn_with_state(session_store.clone(), session_middleware));

		    // Start the server
		    let listener = match tokio::net::TcpListener::bind(&server_url).await {
		        Ok(listener) => listener,
		        Err(e) => {
		            tracing::error!("Failed to bind to {}: {}", server_url, e);
		            std::process::exit(1);
		        }
		    };

		    tracing::info!("Server listening on http://{}", server_url);

		    if let Err(e) = axum::serve(listener, app)
		     .with_graceful_shutdown(shutdown_signal())
		     .await {
		        tracing::error!("Server error: {}", e);
		        std::process::exit(1);
		    }
		}
	
	

This should work for most simple Rust applications.

WORDCOUNT: 312 words.

Latest Blog Posts

  1. Creating post hit counter for FolderHQ and its complexities.
    02 Mar 2026
  2. How to setup CORS layer in a Rust application.
    23 Feb 2026
  3. In search of the best memory allocator that can replace Rust's default system allocator.
    16 Feb 2026
  4. Why your Rust release build tends to use so much memory.
    09 Feb 2026
  5. The main 2 reasons I moved away from Go/Golang and towards Rust.
    07 Feb 2026