What is PM2?
The Problem with node app.js
When you SSH into a server and run your app directly:
node app.js
Three things happen that make this unsuitable for production:
- The process dies when you close the SSH session — it's tied to your terminal
- A crash kills the app — nothing restarts it automatically
- Server reboots kill the app — it doesn't come back after a restart
PM2 solves all three.
How PM2 Works
PM2 runs as a daemon — a background service that outlives your SSH session. It:
- Starts your Node.js app as a managed process
- Monitors it and restarts it if it crashes
- Can generate a startup script so it relaunches after a server reboot
- Collects stdout/stderr into log files you can read at any time
Installing PM2
npm install -g pm2
Verify:
pm2 --version
Core Commands
Starting an App
pm2 start app.js # start with default name ("app")
pm2 start app.js --name my-api # give it a meaningful name
pm2 start app.js --watch # restart on file changes (dev use)
pm2 start npm -- start # run `npm start` via PM2
Viewing Status
pm2 status # list all managed processes with CPU/memory
pm2 list # alias for status
pm2 show my-api # detailed info about a specific process
Example output of pm2 status:
┌─────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┐
│ id │ name │ status │ cpu │ memory │ uptime │ restarts│
├─────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┤
│ 0 │ my-api │ online │ 0% │ 45.3mb │ 2h │ 0 │
└─────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┘
Logs
pm2 logs # stream logs from all processes
pm2 logs my-api # logs for a specific process
pm2 logs --lines 200 # show last 200 lines
pm2 flush # clear all log files
Restarting and Stopping
pm2 restart my-api # restart (brief downtime)
pm2 reload my-api # zero-downtime reload (graceful restart)
pm2 stop my-api # stop without removing from PM2's list
pm2 delete my-api # stop and remove from PM2's list
Cluster Mode
Node.js runs on a single thread. On a server with 8 CPU cores, you're only using one. PM2's cluster mode forks your app across all available cores, multiplying throughput:
pm2 start app.js --name my-api -i max # -i max = one instance per CPU core
pm2 start app.js -i 4 # exactly 4 instances
PM2 automatically load-balances incoming connections across all instances. This is effectively free horizontal scaling without any code changes.
Surviving Server Reboots
By default, PM2's process list is lost on reboot. Fix this with:
pm2 startup # generates and prints a command to run
# → copy and run the printed command (it'll look like: sudo env PATH=... pm2 startup systemd -u ubuntu --hp /home/ubuntu)
pm2 save # saves the current process list to disk
After this, PM2 will restart all your apps automatically whenever the server boots.
Real-Time Monitoring
pm2 monit
Opens a terminal dashboard showing CPU usage, memory, logs, and event loop delay for all processes in real time.