All posts
PM2 Node.js process manager dashboard with terminal
  • PM2
  • Node.js
  • Deployment
  • Process Management
  • VPS

PM2 Node.js Process Management Guide

A complete guide to PM2 for Node.js applications — starting, stopping, monitoring, clustering, log management, ecosystem config files, and surviving server reboots.

4 min read

PM2 is the standard process manager for Node.js applications in production. It keeps your app running after crashes, restarts it on server reboots, provides built-in log management, and supports cluster mode for multi-core performance. This guide covers everything you need for a production setup.

Installation

Install PM2 globally with npm:

sudo npm install -g pm2

Verify the installation:

pm2 --version

Starting Applications

Start a script directly

pm2 start app.js --name "my-app"

Start an npm script

pm2 start npm --name "my-app" -- start

Start a specific entry point

For Astro (Node adapter), Next.js standalone, or any custom server file:

# Astro (Node adapter)
pm2 start dist/server/entry.mjs --name "astro-app"

# Next.js standalone
pm2 start .next/standalone/server.js --name "next-app"

# Custom Express server
pm2 start server.js --name "api-server"

For a complete Astro + Nginx + PM2 setup, see Deploying Astro on a VPS with Nginx. For Next.js deployments, see Deploying Next.js with Nginx or Deploying Next.js with Apache2.

Pass environment variables at start

pm2 start app.js --name "my-app" --env production
# or explicitly:
PORT=8080 NODE_ENV=production pm2 start app.js --name "my-app"

Core Process Commands

pm2 list                    # List all running processes
pm2 status                  # Same as pm2 list
pm2 show my-app             # Detailed info for one process

pm2 stop my-app             # Stop (keeps in list)
pm2 start my-app            # Start a stopped process
pm2 restart my-app          # Restart (brief downtime)
pm2 reload my-app           # Zero-downtime restart (cluster mode)
pm2 delete my-app           # Remove from list entirely

pm2 stop all                # Stop all processes
pm2 restart all             # Restart all processes
pm2 delete all              # Remove all processes

Processes can be referenced by name or by their numeric ID shown in pm2 list.


Surviving Server Reboots

This is the most important step for production. Without it, your app won’t restart after a reboot.

1. Generate a startup script

pm2 startup

PM2 prints a command tailored to your system. Copy and run it — it looks like:

sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu

2. Save the current process list

pm2 save

This saves the list of running processes to ~/.pm2/dump.pm2. On reboot, PM2 restores them automatically.

Run pm2 save again whenever you add, remove, or change a process.

3. Verify startup is registered

pm2 ls          # confirm processes are listed
sudo systemctl status pm2-$(whoami)

Ecosystem Configuration File

For anything beyond a simple one-liner, use an ecosystem file. It keeps all your PM2 configuration in version control.

Create ecosystem.config.cjs in your project root:

// ecosystem.config.cjs
module.exports = {
  apps: [
    {
      name: 'my-app',
      script: 'dist/server/entry.mjs',

      // Number of instances — 'max' uses all CPU cores
      instances: 1,

      // Restart automatically on crash
      autorestart: true,

      // Watch files and restart on changes (use in dev only)
      watch: false,

      // Memory limit — restart if exceeded
      max_memory_restart: '512M',

      // Environment variables per mode
      env: {
        NODE_ENV: 'development',
        PORT: 4321,
      },
      env_production: {
        NODE_ENV: 'production',
        PORT: 4321,
      },
    },
  ],
};

Start with the ecosystem file:

# Development environment
pm2 start ecosystem.config.cjs

# Production environment
pm2 start ecosystem.config.cjs --env production

Other commands work the same way:

pm2 restart ecosystem.config.cjs --env production
pm2 reload ecosystem.config.cjs --env production   # zero-downtime
pm2 stop ecosystem.config.cjs
pm2 delete ecosystem.config.cjs

Cluster Mode

Cluster mode spawns one process per CPU core and load-balances incoming connections across them. This is the fastest way to use all cores on a multi-core VPS without changing your app code.

// ecosystem.config.cjs
module.exports = {
  apps: [
    {
      name: 'my-app',
      script: 'server.js',
      instances: 'max',     // one per CPU core
      exec_mode: 'cluster', // required for load balancing
      autorestart: true,
      env_production: {
        NODE_ENV: 'production',
        PORT: 3000,
      },
    },
  ],
};

In cluster mode, use pm2 reload instead of pm2 restart to achieve zero-downtime updates — PM2 cycles workers one at a time.

Caution: Cluster mode requires your app to be stateless. In-memory session storage, WebSocket connections, and anything stored in a global variable will not be shared across workers. Use Redis or a database for shared state.


Log Management

View logs

pm2 logs                  # Stream all logs
pm2 logs my-app           # Stream logs for one app
pm2 logs my-app --lines 100  # Show last 100 lines

Log file locations

Logs are stored in ~/.pm2/logs/:

~/.pm2/logs/my-app-out.log   # stdout
~/.pm2/logs/my-app-error.log # stderr

Flush logs

pm2 flush            # Delete all log files
pm2 flush my-app     # Delete logs for one app

Log rotation

Install the PM2 log rotation module to avoid logs filling up the disk:

pm2 install pm2-logrotate

Configure it:

pm2 set pm2-logrotate:max_size 50M      # rotate when file exceeds 50 MB
pm2 set pm2-logrotate:retain 14         # keep 14 rotated files
pm2 set pm2-logrotate:compress true     # gzip rotated files
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss

Monitoring

Built-in terminal dashboard

pm2 monit

Shows CPU and memory usage per process in real time.

Process metrics

pm2 show my-app

Displays uptime, restart count, memory, CPU, log paths, and more.

Web dashboard (PM2 Plus)

PM2 offers a hosted web dashboard at app.pm2.io. Free tier available. Connect with:

pm2 link <secret_key> <public_key>

Deployment Workflow

A typical deployment after a code update:

# 1. Pull latest code on server
git pull

# 2. Install any new dependencies
npm install --omit=dev

# 3. Rebuild (if applicable)
npm run build

# 4. Reload the process (zero-downtime in cluster mode, brief restart otherwise)
pm2 reload my-app

# 5. Save the process list if anything changed
pm2 save

Watch Mode (Development Only)

PM2 can watch files and restart the process automatically on changes. Never use this in production — it restarts on every file modification and causes excessive CPU usage.

pm2 start app.js --name "dev-app" --watch
pm2 start app.js --name "dev-app" --watch --ignore-watch="node_modules logs"

Important Notes

  • Always run pm2 save after adding or changing processes, so the state persists across reboots.
  • In cluster mode, use pm2 reload not pm2 restart to achieve zero-downtime updates.
  • Avoid --watch in production — it is for development only.
  • Store your ecosystem.config.cjs in version control so your PM2 setup is reproducible.
  • Use pm2-logrotate on any long-running server to prevent logs from filling your disk.

Frequently Asked Questions

What’s the difference between pm2 restart and pm2 reload?

restart kills the process and starts a new one — there is a brief moment of downtime. reload (cluster mode only) replaces workers one at a time while the others continue handling requests, achieving zero downtime.

My app isn’t restarting after a server reboot. What’s wrong?

You likely skipped one of the two steps: running the pm2 startup command (including the sudo env ... command it prints) and running pm2 save. Both are required.

How do I run multiple apps on the same server?

List them all in the apps array of your ecosystem file, or start each one separately with a unique --name. Give each app a different port and create a separate Nginx server block for each domain.

How do I set environment variables securely?

Don’t store secrets in ecosystem.config.cjs if it’s in version control. Instead, set them in a .env file on the server and load them at startup, or export them in the shell before running PM2. Alternatively use the env_production block in the ecosystem file for non-sensitive config only.

Can PM2 manage non-Node.js processes?

Yes — PM2 can manage any executable. Use interpreter: 'python3' or interpreter: 'none' in the ecosystem file. However, PM2 was designed for Node.js and its language-specific features (cluster mode, --harmony flags, etc.) only apply to Node.js processes.

How do I completely uninstall PM2?

pm2 delete all
pm2 unstartup
sudo npm uninstall -g pm2
rm -rf ~/.pm2