In this lesson, you will learn how to replace your running Node.js application with a new version without dropping a single incoming request.
When you deploy a new version of an application, simply restarting the server causes a brief period where the port is closed, leading to "Connection Refused" errors for your users. To prevent this, we use a technique called Phased Server Replacement, often orchestrated by a process manager or a load balancer.
The Graceful Shutdown Pattern
The core idea is to keep the old server process alive just long enough to finish handling the requests it is currently processing, while the new process begins taking over. In Node.js, we achieve this by listening for the SIGTERM signal.
When you initiate a deployment, your process manager sends SIGTERM to the old worker. Instead of killing it immediately, you stop accepting new connections and wait for existing ones to close:
process.on('SIGTERM', () => {
console.log('Received SIGTERM. Starting graceful shutdown...');
// Stop accepting new connections
server.close(() => {
console.log('All requests finished. Exiting process.');
process.exit(0);
});
});
Implementing Phased Replacement
To ensure continuous availability, you combine this with Clustering or a Reverse Proxy. By running multiple workers (which you’ve already explored in our clustering lessons), you can replace them one by one.
- Spin up a new worker (v2) alongside your existing workers (v1).
- Once the new worker is healthy and ready to process requests, signal the v1 worker to shut down gracefully.
- Because the v1 worker uses the logic above, it will finish its current tasks while the v2 worker immediately starts picking up all new traffic arriving at the gateway.
By staggering this across your worker pool, the system maintains its total request capacity throughout the entire deployment cycle. Your users remain blissfully unaware that the underlying code has been swapped out from under them, as the gateway layer ensures traffic is only routed to processes currently in a "ready" state.
Key Takeaway: Zero-downtime is achieved by signaling old processes to stop accepting new work while they finish their current queue, allowing new processes to take over seamlessly.