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
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
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
}
}]
};
# Start with production env
pm2 start ecosystem.config.js --env production
# Reload zero-downtime
pm2 reload ecosystem.config.js --env production
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)
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
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);
I built ARIA to solve exactly this.
Try it free at step2dev.com — no credit card needed.
Top comments (0)