Graceful Shutdown
Overview
When you deploy a new version of your app (or Kubernetes scales down your pod), the OS sends a SIGTERM signal to Node to kill the process. If Node instantly dies, any user currently in the middle of a credit card transaction or a database write will have their connection violently severed, resulting in corrupted data or 502 Bad Gateway errors. A 'Graceful Shutdown' intercepts the kill signal, stops accepting new traffic, waits for the current traffic to finish processing, safely closes the database, and THEN exits.
Syntax
const express = require('express');
const app = express();
const server = app.listen(3000);
// --- THE GRACEFUL SHUTDOWN LOGIC ---
// 1. Listen for the OS Kill Signal (Docker/Kubernetes sends SIGTERM)
process.on('SIGTERM', () => {
console.log('SIGTERM signal received: closing HTTP server');
// 2. Stop accepting NEW incoming connections immediately!
server.close(async () => {
console.log('HTTP server closed. All active requests have finished.');
try {
// 3. Safely disconnect from the Database, flush Redis queues, etc.
await db.pool.end();
console.log('Database connections safely closed.');
// 4. Finally, kill the process with success code (0)
process.exit(0);
} catch (err) {
console.error('Error during shutdown', err);
process.exit(1); // Exit with failure code
}
});
});Common Pitfalls
- Zombie Keep-Alive Connections. By default, HTTP/1.1 uses 'Keep-Alive' connections. Browsers keep the TCP socket open for seconds/minutes even after the request finishes.
server.close()waits for ALL sockets to close. If a browser refuses to close its keep-alive socket, your Graceful Shutdown will hang indefinitely until Kubernetes violently hard-kills it (SIGKILL). You must implement a timeout mechanism to forcefully destroy idle sockets during shutdown. - Unhandled Rejections. If your shutdown logic (
await db.pool.end()) hangs forever because the database server went offline, the app never shuts down. Always wrap your shutdown logic in a strict 10-second timeout.
Interview Questions
SIGTERM and SIGKILL?SIGTERM is a polite request from the Operating System asking the process to shut itself down. The process can intercept this and run cleanup code. SIGKILL (often executed as kill -9) is a brutal, un-interceptable command. The OS instantly strips the process from memory. A process cannot listen for or stop a SIGKILL.
Real-World Example
Implementing a strict timeout during a graceful shutdown. If the cleanup takes longer than 10 seconds, we force-kill the app to prevent it from hanging during a deployment.
process.on('SIGTERM', () => {
console.log("Shutting down gracefully...");
// FAILSAFE: If the cleanup takes more than 10 seconds, murder the process.
setTimeout(() => {
console.error("Cleanup took too long! Forcefully exiting.");
process.exit(1);
}, 10000).unref(); // .unref() ensures this timer doesn't keep Node alive itself!
server.close(() => {
db.disconnect().then(() => process.exit(0));
});
});Check Your Knowledge
Test your understanding of Graceful Shutdown with these quick questions.