Zero-downtime Node.js deployments with PM2 on a VPS
PM2 cluster mode, rolling restarts, and a simple deploy script. Ship updates without dropping a single request.
Deploying a Node.js app by SSHing in, killing the process, and restarting it will drop every active connection. For a low-traffic hobby project that's fine. For anything real, you need zero-downtime restarts.
PM2 makes this simple with cluster mode and reload. Here's exactly how to set it up.
Why cluster mode?
Node.js is single-threaded. On a multi-core server, a single Node process leaves CPU cores idle. PM2's cluster mode forks your app across all available cores and load-balances incoming connections between them.
Cluster mode also enables zero-downtime restarts: PM2 reloads workers one at a time, keeping at least one worker alive throughout the process.
Step 1: Install PM2
npm install -g pm2 Or use Simplewala's Node.js installer, which includes PM2 automatically.
Step 2: Start your app in cluster mode
pm2 start npm --name "my-app" -i max -- start -i max forks one worker per CPU core. You can also specify a number: -i 4.
Save the process list so PM2 restarts your app after a server reboot:
pm2 save
pm2 startup Step 3: Zero-downtime reload
Use reload instead of restart when deploying updates:
pm2 reload my-app
PM2 sends SIGINT to one worker at a time and waits for it to finish handling
in-flight requests before starting a new worker. Active connections are never dropped.
A simple deploy script
Create /srv/app/deploy.sh:
#!/bin/bash
set -e
cd /srv/app
git pull origin main
npm ci --production
npm run build
pm2 reload my-app
echo "Deploy complete" chmod +x /srv/app/deploy.sh Run it from your CI/CD pipeline or a GitHub Actions workflow:
- name: Deploy
run: ssh root@$SERVER_IP '/srv/app/deploy.sh' Environment variables
Never hardcode secrets in your source code. Create a .env file on the server and
reference it in your PM2 ecosystem config:
// ecosystem.config.cjs
module.exports = {
apps: [{
name: 'my-app',
script: 'npm',
args: 'start',
instances: 'max',
exec_mode: 'cluster',
env_file: '/srv/app/.env',
}]
}; pm2 start ecosystem.config.cjs Monitoring
PM2 includes a built-in monitor:
pm2 monit On Simplewala, PM2 logs are also visible in the portal under Server → Applications without needing SSH.
Summary
- Use
-i maxto fork across all CPU cores - Use
pm2 reload(notrestart) for zero-downtime deploys - Persist your process list with
pm2 save+pm2 startup - Store secrets in
.envand reference them viaenv_file
Ready to simplify your hosting?
Deploy your first server in 90 seconds. All features included.
Start free