# PM2 Deployment & Usage Guide
Production Process Manager for Node.js/Bun applications with built-in load balancing.
## Prerequisites
- **Runtime**: Node.js 12.X+ or Bun 1.1.25+
- **Package Manager**: NPM (included with Node.js) or Bun
- **OS**: Linux (recommended), macOS, or Windows
- **Optional**: NVM or FNM for Node.js version management
## Installation
### Global Installation (Recommended)
**Via NPM:**
```bash
npm install pm2@latest -g
Via Bun:
bun install pm2 -g
Note for Bun users: If using Bun exclusively, symlink it to node:
sudo ln -s /home/$USER/.bun/bin/bun /usr/bin/node
Verify Installation
pm2 --version
pm2 list
Configuration
1. Ecosystem File (Recommended)
Create ecosystem.config.js for production-grade configuration:
module.exports = {
apps: [{
name: 'app-name',
script: './app.js',
instances: 'max', // or -1 (all CPUs minus 1) or specific number
exec_mode: 'cluster', // enables load balancing
watch: false, // enable for development only
max_memory_restart: '1G',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
},
log_date_format: 'YYYY-MM-DD HH:mm Z',
error_file: './logs/err.log',
out_file: './logs/out.log',
merge_logs: true,
// PM2+ monitoring (optional)
public_key: process.env.KEYMETRICS_PUBLIC,
secret_key: process.env.KEYMETRICS_SECRET,
machine_name: process.env.INSTANCE_NAME
}]
};
2. Environment Variables
PM2_HOME: Custom directory for PM2 logs, pids, and socket filesPM2_SILENT: Set totrueto suppress outputKEYMETRICS_PUBLIC/KEYMETRICS_SECRET: For PM2+ monitoring integrationINSTANCE_NAME: Machine name for PM2+ dashboard
3. Generate Startup Script
Configure PM2 to start on boot:
# Detect init system and generate startup script
pm2 startup
# Save current process list
pm2 save
# Remove startup script (if needed)
pm2 unstartup
Supported init systems: systemd, upstart, launchd, rc.d
Build & Run
Basic Operations
Start an application:
# Single instance (fork mode)
pm2 start app.js
# Named process
pm2 start app.js --name "api-server"
# Cluster mode (utilize all CPUs)
pm2 start app.js -i max
# Specific instances
pm2 start app.js -i 4
# Via ecosystem file
pm2 start ecosystem.config.js
Process Management:
pm2 list # List all processes
pm2 stop <app_name|id|all> # Stop process(es)
pm2 restart <app_name|id|all>
pm2 delete <app_name|id|all>
pm2 describe <id|app_name> # Detailed metrics
Development vs Production
Development:
# Watch mode (auto-restart on file changes)
pm2 start app.js --watch --ignore-watch="node_modules"
# Tail logs
pm2 logs
Production:
# Start with production env
pm2 start ecosystem.config.js --env production
# Zero-downtime reload (for cluster mode)
pm2 reload all
pm2 reload <app_name>
# Enable host monitoring
pm2 set pm2:sysmonit true
pm2 update
Monitoring & Logs
Real-time monitoring:
pm2 monit # Interactive dashboard
pm2 logs # Stream logs
pm2 logs --json # JSON formatted logs
pm2 logs --format # Formatted output
pm2 logs app-name # Specific app logs
Log Management:
pm2 flush # Clear all logs
pm2 reloadLogs # Reload log files (for logrotation)
# Install log rotation module
pm2 install pm2-logrotate
Deployment
1. Docker Deployment
Use pm2-runtime as a drop-in replacement for node:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
RUN npm install pm2 -g
COPY . .
EXPOSE 3000
CMD ["pm2-runtime", "app.js", "-i", "max"]
Or with npm scripts:
CMD ["pm2-runtime", "npm", "--", "start"]
2. Bare Metal/VM Deployment
Initial Setup:
# On server
npm install pm2 -g
pm2 startup systemd
pm2 start ecosystem.config.js --env production
pm2 save
Update Deployment:
# Zero-downtime deployment script
npm install pm2@latest -g
pm2 update
pm2 reload ecosystem.config.js --env production
3. PM2+ (Multi-Server Monitoring)
For monitoring across multiple servers:
- Create account at https://app.pm2.io/
- Link your PM2 instance:
pm2 link <secret_key> <public_key> [machine_name]
Troubleshooting
Common Issues
1. Bun Compatibility
- Error:
PM2 cannot run on Bun version < 1.1.25 - Solution: Upgrade Bun to v1.1.25 or higher for cluster support
2. Port Already in Use
- Error: EADDRINUSE when starting multiple instances
- Solution: Ensure your app uses
process.env.PORTor let PM2 handle port assignment in cluster mode
3. Silent Mode Not Working
- Issue: PM2 still outputs logs despite
-sor--silent - Solution: Place silent flags before the
--separator:pm2 -s start app.js -- --arg1
4. Environment Variables Not Updating
- Issue: Old env vars persist after changes
- Solution: Use
--update-envflag:pm2 restart app --update-env
5. Permission Denied on Startup
- Issue:
pm2 startupfails with permission errors - Solution: Run the exact command provided by
pm2 startupoutput (usually requires sudo)
6. Log Files Growing Too Large
- Solution: Install logrotate module immediately:
pm2 install pm2-logrotate
7. Process Not Starting
- Check:
pm2 logs <app-name> pm2 describe <app-name> - Verify: Interpreter path if using non-Node.js binaries (Python, Ruby, etc.)
pm2 start script.py --interpreter python3
Update PM2 Safely
npm install pm2@latest -g
pm2 save # Backup process list
pm2 update # Seamless update (preserves running processes)
Reset Statistics
pm2 reset <app_name> # Reset counters for specific app
pm2 reset all # Reset all counters