Course contentsShow
← Node.js
Lesson 1107 of 1,98010. Real-time Communication and WebsocketsFree lesson

Implementing Graceful Shutdown Procedures

You will ensure that closing a server process cleans up all active socket connections properly.

In this lesson, you will learn how to safely stop your Node.js WebSocket server by ensuring all active client connections are cleanly closed before the process exits.

Why Graceful Shutdowns Matter

When you stop a Node.js process abruptly (e.g., via Ctrl+C or a deployment signal), active WebSocket connections are severed instantly. To the client, this looks like a network failure rather than a scheduled maintenance event. This can lead to lost messages, corrupted state, or abrupt UI "reconnecting" loops. A graceful shutdown allows your server to notify clients, finish processing current tasks, and close sockets politely.

The Shutdown Workflow

To implement this, we listen for termination signals like SIGTERM or SIGINT. When these occur, we perform three distinct steps:

  1. Stop accepting new connections: Tell the server to stop listening for new handshake requests.
  2. Notify clients: Emit a "server-closing" event so clients can pause operations or show a "Going offline" notice.
  3. Close existing connections: Force-close active sockets to allow the event loop to empty.

Here is how you handle the process signals:

process.on('SIGTERM', async () => {
  console.log('Shutting down gracefully...');

  // 1. Stop the HTTP server from accepting new connections
  server.close(async () => {
    console.log('HTTP server closed.');
    process.exit(0);
  });

  // 2. Notify all connected clients
  io.emit('server-maintenance', { message: 'Server is restarting' });

  // 3. Close all active socket connections
  // Depending on your version, you can iterate through the adapter
  for (const [id, socket] of io.of('/').sockets) {
    socket.disconnect(true); // 'true' forces the close
  }
});

Considerations for Real-Time Apps

If you are using a distributed setup (like a Redis adapter), ensure your shutdown sequence waits for any pending Pub/Sub events to clear before calling process.exit(0). By signaling the intent to close before terminating the process, you provide a seamless transition for your users, allowing their client-side logic to trigger a clean "offline" state rather than an unexpected error.

Key Takeaway: A graceful shutdown ensures that by notifying clients and closing existing sockets before terminating the process, you prevent data loss and provide a professional, error-free experience during deployments.