PM2 cluster mode is the secret sauce for Node.js zero-downtime deploys, letting you swap out your app’s code without dropping a single request.

Let’s see it in action. Imagine you have a simple Node.js app:

// app.js
const http = require('http');

const server = http.createServer((req, res) => {
  // Simulate some work
  setTimeout(() => {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from Node.js!\n');
  }, 500);
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});

Now, let’s run this with PM2 in cluster mode. First, install PM2 globally:

npm install pm2 -g

Start your app, telling PM2 to use multiple instances (the cluster mode is the default for Node.js apps):

pm2 start app.js -i max

The -i max tells PM2 to spawn as many Node.js processes as there are CPU cores on your machine. You can also specify a number, like -i 4 for four processes.

Now, if you check pm2 list, you’ll see multiple instances of your app.js running:

┌─────┬──────────┬───────────┬─────┬─────┬───────────┬──────────┬──────────┐
│ id  │ name     │ mode      │ ↺   │ cpu │ memory    │ watching │ status   │
├─────┼──────────┼───────────┼─────┼─────┼───────────┼──────────┼──────────┤
│ 0   │ app      │ cluster   │ 3   │ 0%  │ 25.4 MB   │ enabled  │ online   │
│ 1   │ app      │ cluster   │ 3   │ 0%  │ 25.4 MB   │ enabled  │ online   │
│ 2   │ app      │ cluster   │ 3   │ 0%  │ 25.4 MB   │ enabled  │ online   │
│ 3   │ app      │ cluster   │ 3   │ 0%  │ 25.4 MB   │ enabled  │ online   │
└─────┴──────────┴───────────┴─────┴─────┴───────────┴──────────┴──────────┘

PM2 acts as a load balancer. When a request comes in, PM2 directs it to one of the available Node.js processes. This is crucial for zero-downtime deployments.

To deploy an update without downtime, you’d typically:

  1. Update your code: Change app.js. For example, change the response to "Hello from updated Node.js!".

  2. Reload PM2: Use the pm2 reload command.

    pm2 reload app
    

    Or, if you have multiple apps and want to be specific:

    pm2 reload 0  # Reloads the process with id 0
    

What pm2 reload does is magical. It doesn’t kill all your processes at once. Instead, it gracefully restarts them one by one. PM2 sends a SIGUSR2 signal to one of your running Node.js processes. The process receiving this signal:

  • Stops accepting new connections.
  • Finishes processing its current requests.
  • Then, it exits.
  • PM2 immediately starts a new instance of your application.

This cycle repeats for each process. While one process is being replaced, the others are still handling requests, ensuring no downtime.

The core problem PM2 cluster mode solves is that Node.js, by default, is single-threaded. If your Node.js process crashes or is restarted, your entire application becomes unavailable. Cluster mode leverages the operating system’s ability to create multiple processes and uses a master process (PM2 itself) to manage them. This master process can then orchestrate rolling restarts.

The master process in PM2 also handles monitoring. If any of your worker processes crash, the master detects it and restarts it automatically, ensuring your application stays online.

The real power comes when you combine this with a deployment script. Imagine a deploy.sh file:

#!/bin/bash
# deploy.sh

# Navigate to your app directory
cd /path/to/your/app

# Pull the latest code
git pull origin main

# Install dependencies
npm install

# Reload PM2 with the new code
pm2 reload app --update-env

When you run bash deploy.sh, your application will be updated and reloaded with zero perceived downtime by your users. The --update-env flag is useful if you’ve also updated environment variables and want PM2 to pick them up during the reload.

A common pitfall is misunderstanding how signals work. While SIGUSR2 is the default for graceful reload, PM2 also responds to SIGINT (which is what Ctrl+C sends) to stop the entire application, and SIGTERM to stop all worker processes. If you manually send SIGINT to a worker process, PM2 will restart it, but if you send it to the master PM2 process, your whole application goes down.

The next concept you’ll want to explore is advanced configuration with PM2, like setting up perpetual restarts on uncaught exceptions, using log management features, and integrating with process managers like systemd for robust startup.

Want structured learning?

Take the full Nodejs course →