Node.js Production Deployment on a VPS with PM2 in 2026

Published on | Updated on

Node.js in production needs process management, clustering, and monitoring. PM2 handles all three. Here's the complete production deployment setup.

Written by Jochem, Infrastructure Engineer at Space-Node, 5-10 years experience in game server hosting, VPS infrastructure, and 24/7 streaming solutions. Read author bio →

Running node app.js in a terminal is not production deployment. If the terminal closes, the process dies. If the app crashes, it stays dead. If the server reboots, it doesn't restart. PM2 solves all of this.

PM2 Installation and Basic Use

npm install -g pm2

# Start your application
pm2 start app.js --name "my-app"

# With environment mode
pm2 start app.js --name "my-app" --env production

# Start on system boot
pm2 startup
pm2 save  # Save current process list to resurrect on reboot

Ecosystem Configuration File

For production, use an ecosystem file instead of command-line flags:

// ecosystem.config.js
module.exports = {
    apps: [{
        name: 'my-api',
        script: 'dist/server.js',  // or build output
        instances: 'max',          // Use all CPU cores
        exec_mode: 'cluster',      // Fork for single-threaded, cluster for HTTP
        
        env_production: {
            NODE_ENV: 'production',
            PORT: 3000
        },
        
        // Logging
        log_file: '/var/log/myapp/combined.log',
        error_file: '/var/log/myapp/error.log',
        
        // Auto-restart on memory leak
        max_memory_restart: '500M',
        
        // Restart if file watches change (useful for simple deployments)
        watch: false  // Keep false in production
    }]
};
pm2 start ecosystem.config.js --env production

Nginx as Reverse Proxy

server {
    listen 443 ssl;
    server_name api.yourdomain.com;
    
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';  # For WebSocket support
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_cache_bypass $http_upgrade;
    }
}

Deployment Update Script

#!/bin/bash
# deploy.sh
set -e

cd /var/www/my-app
git pull origin main
npm ci --production
npm run build
pm2 reload my-api --update-env  # Graceful zero-downtime reload

echo "Deployment complete"

Monitoring

pm2 monit                    # Real-time dashboard (CPU, memory, log)
pm2 logs my-api --lines 50   # Recent logs
pm2 status                   # Process overview

Deploy your Node.js API on Space-Node VPS

Why PM2 in 2026

PM2 has been the de-facto Node.js process manager since 2015 and is still the simplest way to run Node in production. Alternatives (systemd, Docker, Kubernetes) are valid but heavier.

What PM2 gives you:

  • Auto-restart on crash.
  • Cluster mode (multiple workers per CPU).
  • Log rotation.
  • One-line zero-downtime reload.
  • Built-in metrics endpoint.
  • Startup script generation for systemd / launchd.

What it doesn't give you:

  • Container isolation (use Docker for that).
  • Multi-host orchestration (use k8s).
  • Network policy / service mesh.

Install

npm install -g pm2

For production, install on a non-root user:

adduser --system --group --home /home/app app
sudo -u app npm install --prefix /home/app/.npm-global -g pm2

Ecosystem file (preferred over CLI flags)

ecosystem.config.cjs:

module.exports = {
  apps: [{
    name: 'web',
    script: './dist/index.js',
    instances: 'max',
    exec_mode: 'cluster',
    max_memory_restart: '512M',
    env_production: {
      NODE_ENV: 'production',
      PORT: 3000,
    },
    error_file: './logs/web-err.log',
    out_file:   './logs/web-out.log',
    merge_logs: true,
    time: true,
  }],
};

instances: 'max' runs one worker per CPU core. exec_mode: 'cluster' enables Node's built-in cluster module for shared-port load balancing.

Start, monitor, persist

pm2 start ecosystem.config.cjs --env production
pm2 status
pm2 logs web --lines 100
pm2 monit                    # ncurses dashboard
pm2 save                     # persist current process list
pm2 startup systemd          # generate systemd boot script (run as root)

pm2 save + pm2 startup is the combination that makes processes survive reboot. Skipping either means PM2 forgets your apps after the next restart.

Zero-downtime deploys

# during deploy
git pull
npm ci --omit=dev
npm run build
pm2 reload web              # workers restart one-by-one, no dropped requests

reload (not restart) is what makes it zero-downtime in cluster mode. Each worker gets a SIGINT, finishes in-flight requests, then a new worker takes its place.

Log rotation

pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7
pm2 set pm2-logrotate:compress true

Without rotation, out.log grows to GB and starves the disk. We've debugged "server slow" issues that turned out to be a 40 GB log file filling /var.

Common breakage

SymptomCauseFix
App died, didn't restartcrash loop > 15 in 60s = give upfix the crash, then pm2 start
"max_memory_restart" loopsmemory leak on hot pathprofile with --inspect, fix leak
Port already in useold PM2 instance from prior userpm2 list as the right user
pm2 restart drops requestsusing restart not reloaduse reload in cluster mode
OOM after rotation runslog files held by deleted FDrestart pm2-logrotate; fix node process if it grew unbounded

When to switch off PM2

  • You're moving to containers anyway: drop PM2, let Kubernetes / Docker handle restart and scaling.
  • You only run one process and don't need cluster mode: a plain systemd unit is simpler.
  • You need better metrics: PM2 Plus is paid; Prometheus + node-exporter is free.

For a single VPS running 1-5 Node services, PM2 is still the right answer in 2026.

Jochem

About the Author

Jochem, Infrastructure Engineer at Space-Node, expert in game server hosting, VPS infrastructure, and 24/7 streaming solutions with 5-10 years experience.

Since 2023
500+ servers hosted
4.8/5 avg rating

I specialize in Minecraft, FiveM, Rust, and 24/7 streaming infrastructure, operating enterprise-grade AMD Ryzen 9 hardware in Netherlands datacenters.

View my full bio and credentials →

Launch Your VPS Today

Get started with professional VPS hosting powered by enterprise hardware. Instant deployment and 12/7 support included.