Course contentsShow
← Node.js
Lesson 639 of 1,9807. Web Framework Architecture and MiddlewareFree lesson

Graceful Shutdown Coordination

Manage server termination by draining active connections before closing the process.

In this lesson, you will learn how to prevent data corruption and dropped requests by ensuring your Node.js server finishes processing active work before shutting down.

The Problem: The Abrupt Exit

When you stop a Node.js process (e.g., using Ctrl+C or a deployment signal like SIGTERM), the default behavior is to kill the process immediately. If a request is currently being processed or a database transaction is halfway through, those operations are severed instantly. This leads to broken connections, incomplete database writes, and frustrated users who receive "connection reset" errors.

The Solution: Draining Connections

Graceful shutdown is a coordination process where your server stops accepting new requests while it "drains"—or completes—the requests that are already in flight.

In Node.js, we listen for process signals like SIGTERM (the signal sent by most process managers like PM2 or Kubernetes). When received, we trigger a three-step sequence:

  1. Stop accepting new connections: Tell the server to stop listening for incoming traffic.
  2. Finish pending work: Wait for active HTTP requests to reach a response.
  3. Exit the process: Once the connections are clear, call process.exit(0) to finish the lifecycle.

Basic Coordination Pattern

Here is how you coordinate this shutdown inside your application:

const server = app.listen(3000);

const shutdown = () => {
  console.log('Shutdown signal received: closing HTTP server...');
  
  // 1. Stop accepting new connections
  server.close((err) => {
    if (err) {
      console.error('Error during shutdown:', err);
      process.exit(1);
    }
    console.log('HTTP server closed. Exiting process.');
    // 3. Exit with success code
    process.exit(0);
  });
};

// 2. Listen for process signals
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);

By calling server.close(), Node.js stops the server from accepting new sockets but leaves the existing ones open until they naturally complete. Once all active requests finish their cycle, the callback inside server.close triggers, allowing you to perform cleanup tasks like closing database pools before terminating the process entirely. This ensures a clean hand-off for your services.

Key Takeaway: Graceful shutdown transforms a sudden process death into a controlled exit by stopping new traffic while allowing existing request-response cycles to complete naturally.