DEV Community

Yash
Yash

Posted on

How to Run a Node.js App in Production with PM2 (Complete Guide)

How to Run a Node.js App in Production with PM2 (Complete Guide)

Most Node.js tutorials end at node server.js. That's fine for development. In production, you need process management: auto-restart, logging, monitoring, and zero-downtime deploys.

PM2 handles all of this.

Install PM2

npm install -g pm2
Enter fullscreen mode Exit fullscreen mode

Basic Usage

# Start your app
pm2 start server.js --name my-app

# Start with specific Node version
pm2 start server.js --name my-app --interpreter /usr/bin/node

# List running processes
pm2 list

# Monitor live
pm2 monit

# View logs
pm2 logs my-app
pm2 logs my-app --lines 100

# Restart / reload (reload = zero downtime)
pm2 restart my-app
pm2 reload my-app

# Stop / delete
pm2 stop my-app
pm2 delete my-app
Enter fullscreen mode Exit fullscreen mode

The ecosystem.config.js (Use This Always)

Running PM2 from the command line works, but an ecosystem config is more powerful and reproducible:

// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'api',
    script: './src/server.js',

    // Process management
    instances: 'max',           // One per CPU core (cluster mode)
    exec_mode: 'cluster',       // Enable load balancing

    // Memory management
    max_memory_restart: '512M', // Restart if memory exceeds 512MB

    // Crash recovery
    min_uptime: '30s',          // Must stay up 30s to be considered healthy
    max_restarts: 10,           // Max restarts before giving up
    restart_delay: 4000,        // Wait 4s between restarts

    // Zero-downtime deploys
    wait_ready: true,           // Wait for process.send('ready')
    listen_timeout: 10000,      // 10s to emit ready signal
    kill_timeout: 5000,         // 5s to gracefully shut down

    // Logging
    log_file: '/var/log/pm2/api.log',
    out_file: '/var/log/pm2/api-out.log',
    error_file: '/var/log/pm2/api-error.log',
    log_date_format: 'YYYY-MM-DD HH:mm:ss',
    merge_logs: true,

    // Environment
    env: {
      NODE_ENV: 'development',
      PORT: 3000
    },
    env_production: {
      NODE_ENV: 'production',
      PORT: 3000
    }
  }]
};
Enter fullscreen mode Exit fullscreen mode
# Start with production env
pm2 start ecosystem.config.js --env production

# Reload zero-downtime
pm2 reload ecosystem.config.js --env production
Enter fullscreen mode Exit fullscreen mode

Survive Server Reboots

# Generate startup script (run as root or with sudo)
pm2 startup

# Follow the output — it gives you a command to run
# Example output:
# [PM2] To setup the Startup Script, copy/paste the following command:
# sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu

# Save current process list
pm2 save

# Verify it will restart
sudo systemctl status pm2-ubuntu  # (or your username)
Enter fullscreen mode Exit fullscreen mode

Useful PM2 Commands

# Real-time dashboard
pm2 monit

# Show detailed process info
pm2 describe my-app

# Flush logs
pm2 flush my-app

# Rotate logs (set up log rotation)
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7

# Reset restart count
pm2 reset my-app

# Scale up/down instances
pm2 scale my-app 4   # Set to 4 instances
pm2 scale my-app +2  # Add 2 more instances
Enter fullscreen mode Exit fullscreen mode

Graceful Shutdown in Your App

// server.js
const server = app.listen(PORT, () => {
  if (process.send) process.send('ready'); // Signal PM2 we're ready
});

const shutdown = () => {
  server.close(() => {
    // Close DB connections, etc.
    process.exit(0);
  });
  // Force exit if graceful shutdown takes too long
  setTimeout(() => process.exit(1), 5000);
};

process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);
Enter fullscreen mode Exit fullscreen mode

I built ARIA to solve exactly this.
Try it free at step2dev.com — no credit card needed.

Top comments (0)