VPS DeploymentIntermediate 12 min Lesson 21 of 30

PM2 for Node Applications

Keep Node applications running with PM2: cluster mode, zero-downtime reloads, log management, and when systemd is the better choice.

VPS Deployment · Lesson 21 of 30
0/30 done(0%)

What is it? #

PM2 is a process manager for Node applications. It restarts crashed processes, runs several instances across CPU cores, manages logs and supports zero-downtime reloads.

Node is single-threaded, so one process uses one core. PM2's cluster mode starts one process per core and load balances between them, which is the main reason people use it.

It overlaps with systemd. The pragmatic arrangement is systemd managing PM2 itself, so PM2 handles the Node-specific work and the operating system handles boot and supervision.

For a single process with no clustering need, systemd alone is simpler and one fewer moving part.

Think of it like this #

A shift supervisor for a team of identical workers. They assign work evenly, replace anyone who collapses, and can swap the whole team for a fresh one without closing the counter.

The building manager still decides when the doors open — that is systemd.

Simple example #

An Express API on a 4-core server. PM2 runs four instances, reloads them one at a time on deployment, and rotates logs. systemd starts PM2 at boot.

Code #

BASH
sudo npm install -g pm2

# Cluster mode: one process per core, load balanced
pm2 start dist/server.js --name api -i max

pm2 list
pm2 logs api --lines 100
pm2 monit                  # live CPU and memory per process
JAVASCRIPT
// ecosystem.config.js — configuration in the repository, not in shell history
module.exports = {
  apps: [{
    name: 'api',
    script: './dist/server.js',
    instances: 'max',                 // one per CPU core
    exec_mode: 'cluster',

    env_production: { NODE_ENV: 'production', PORT: 3000 },

    max_memory_restart: '500M',       // restart a leaking instance
    kill_timeout: 30000,              // 30s for in-flight requests
    wait_ready: true,                 // wait for process.send('ready')
    listen_timeout: 10000,

    error_file: '/var/log/pm2/api-error.log',
    out_file: '/var/log/pm2/api-out.log',
    merge_logs: true,
    time: true,                       // timestamp every log line
  }],
};
JAVASCRIPT
// The application cooperates with reloads and shutdowns
const server = app.listen(process.env.PORT, () => {
  if (process.send) process.send('ready');      // tell PM2 we are serving
});

process.on('SIGINT', () => {
  server.close(() => process.exit(0));          // finish in-flight requests
});
BASH
# Deployment
pm2 reload ecosystem.config.js --env production   # zero downtime, one at a time
# pm2 restart  → kills and restarts all at once: there IS downtime

# Survive a reboot
pm2 startup systemd                # prints a command to run with sudo
pm2 save                           # remember the current process list

# Logs
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 14
TEXT
PM2 or systemd?

PM2               clustering across cores, zero-downtime reload, built-in
                  log rotation and monitoring, Node-specific ergonomics

systemd           already present, one fewer dependency, journal integration,
                  resource limits, consistent with every other service

A common choice: systemd for a single process, PM2 (supervised by systemd)
when clustering and rolling reloads matter.

How it works #

Cluster mode uses Node's built-in cluster module. A primary process starts workers and distributes incoming connections between them, so four workers use four cores.

wait_ready with process.send('ready') is what makes reloads genuinely zero-downtime. PM2 waits for the new instance to signal it is listening before retiring the old one; without it, PM2 assumes readiness immediately and can route traffic to a process that is not yet serving.

kill_timeout gives a process time to finish in-flight requests after SIGINT. The application's shutdown handler closes the server and exits, which is the same graceful shutdown pattern seen throughout this track.

max_memory_restart restarts an instance that exceeds a memory threshold, containing leaks without waiting for the OOM killer.

pm2 reload replaces instances one at a time, so there are always workers serving. pm2 restart stops everything and starts again, which does cause a gap.

pm2 startup generates a systemd unit so PM2 itself starts at boot, and pm2 save records which applications it should resurrect. Forgetting pm2 save means the process list is empty after a reboot.

Log rotation is not enabled by default. Without the logrotate module, PM2 logs grow indefinitely, which is a common cause of a full disk.

Real-world use #

PM2 is widely used in Node deployments, particularly where clustering matters and the team prefers Node-native tooling.

The main operational gotchas are forgetting pm2 save, using restart instead of reload, and never enabling log rotation.

In container environments PM2 is usually unnecessary. The orchestrator handles restarts and scaling, and running a process manager inside a container adds a layer that complicates signal handling.

For CPU-bound Node work, clustering is the only way to use more than one core in a single machine. For IO-bound work the benefit is smaller, since one event loop handles many concurrent requests.

Either way, the graceful shutdown handler in the application is what makes deployments invisible to users, and that code is required regardless of which manager you choose.

Common mistakes #

  • Using pm2 restart for deployments instead of pm2 reload.
  • Forgetting pm2 save, so nothing comes back after a reboot.
  • No log rotation, letting PM2 logs fill the disk.
  • No graceful shutdown handler, so reloads drop in-flight requests.
  • Running PM2 inside a container where the orchestrator already supervises.

Practice #

Run a Node application under PM2 in cluster mode with an ecosystem file, a ready signal and a shutdown handler. Configure startup and save, enable log rotation, then perform a reload while sending continuous requests and confirm none fail.

Quick quiz

  1. 1. Why does Node benefit from cluster mode?

  2. 2. What is the difference between reload and restart?

  3. 3. What does `wait_ready` require from the application?

  4. 4. What happens if you forget `pm2 save`?

  5. 5. When is PM2 usually unnecessary?

Summary

  • PM2 adds clustering, rolling reloads, log management and monitoring for Node.
  • Use reload, not restart, for deployments.
  • Signal readiness and handle SIGINT for genuinely zero-downtime reloads.
  • Run `pm2 startup` and `pm2 save`, and enable log rotation.
  • systemd alone is fine for a single process; skip PM2 inside containers.