PM2 Cheatsheet - Node.js Process Manager Reference
Running node app.js in the foreground means watching a process die or a memory leak build with no safety net. PM2 layers on daemon supervision, self-restart, cluster mode, logging and boot-start as one loop. This table is grouped into start/run, logs, monitoring, cluster, startup and ecosystem.config.js, with deployment-critical flags, and it calls out CLI differences like reload vs restart and the pm2 save + startup pair for crash recovery. After reading you can set up supervision, scaling and self-healing for a Node service on your own.
Typical Use Case
Before a Node service goes live, start it with -i max to spawn one process per CPU core, then centralize tuning in ecosystem.config.js; when a process crashes or leaks memory, watch trends with pm2 monit and set max_memory_restart to auto-restart over-limit processes; to release without dropping online users use reload for zero-downtime restarts, especially for stateful or long-lived services; to bring everything back after a reboot combine pm2 save with pm2 startup; for daily triage run pm2 list to find non-online processes, then pm2 logs for stack traces.
Start & Stop 12
pm2 start app.jspm2 start app.js --name "api"pm2 start app.js -i maxpm2 start app.js -i 4pm2 start ecosystem.config.jspm2 stop allpm2 stop apipm2 restart apipm2 reload apipm2 delete apipm2 start app.js --watchpm2 killLogs 5
pm2 logspm2 logs api --lines 100pm2 logs api --errpm2 flushpm2 install pm2-logrotateMonitor & Status 6
pm2 listpm2 show apipm2 monitpm2 statuspm2 describe apipm2 jlistStartup 4
pm2 startuppm2 savepm2 resurrectpm2 unstartupCluster & Scale 5
pm2 scale api +2pm2 scale api 8pm2 reset apipm2 serve ./dist 8080pm2 deploy ecosystem.config.js productionecosystem.config.js 6
module.exports = { apps: [{ name: "api", script: "app.js", instances: "max", exec_mode: "cluster" }] }env: { NODE_ENV: "production", PORT: 3000 }max_memory_restart: "1G"error_file: "./logs/err.log", out_file: "./logs/out.log"watch: true, ignore_watch: ["node_modules", "logs"]pm2 start ecosystem.config.js --env productionParameter matrix
| Parameter | Effect | Example |
|---|---|---|
--name <process> | Give the process a stable name that later stop, restart and logs calls all address | pm2 start app.js --name "api" |
-i max | Run one instance per CPU core, the default starting point for production throughput | pm2 start app.js -i max |
-i <N> | Pin an explicit instance count, replacing -i max when core and memory ratios need exact control | pm2 start app.js -i 4 |
pm2 start ecosystem.config.js | Start from the config file, keeping every option in one place instead of scattered shell history | pm2 start ecosystem.config.js |
--env <environment> | Read the env_production section so one config file can serve several environments | pm2 start ecosystem.config.js --env production |
pm2 reload <name|all> | Restart instances one at a time, which reloads without dropping connections in cluster mode | pm2 reload api |
pm2 restart <name|all> | Restart a named process outright to reload its code; the behaviour is the same in both execution modes | pm2 restart api |
pm2 delete <name|all> | Remove it from the process list so it is no longer supervised or restored on boot | pm2 delete api |
--watch | Restart on file changes, removing the manual restart from the development loop | pm2 start app.js --watch |
watch + ignore_watch | Enable auto restart while excluding dependency and log directories, avoiding pointless restart loops | watch: true, ignore_watch: ["node_modules", "logs"] |
pm2 logs --lines <n> | Read only the last N lines, so history cannot drown out the error you just triggered | pm2 logs api --lines 100 |
pm2 logs --err | Emit only the error stream, gathering stack traces and exceptions in one place | pm2 logs api --err |
pm2 flush | Truncate the on-disk log files, reclaiming disk before anything else | pm2 flush |
pm2 install pm2-logrotate | Install the rotation module so logs cannot grow until the disk fills | pm2 install pm2-logrotate |
pm2 show / describe <name> | Inspect the process in detail: start command, restart count, memory, uptime, log paths and launch environment | pm2 describe api |
pm2 monit | Watch CPU and memory on a live panel to judge whether a process leaks slowly | pm2 monit |
pm2 jlist | Emit the process list as JSON so scripts parse structure instead of scraping terminal text | pm2 jlist |
pm2 reset <name|all> | Zero the restart counter so the count reflects the current deployment again | pm2 reset api |
pm2 scale <±N|name> | Add or remove instances online, adjusting capacity without restarting the application | pm2 scale api +2 |
pm2 save / resurrect | Persist the current process list and restore it verbatim, the two ends of the boot-time chain | pm2 resurrect |
pm2 startup / unstartup | Generate or remove the boot script, which only takes effect once you actually run the printed command | pm2 startup |
max_memory_restart | Cap per-process memory and restart on breach, a backstop against leaks rather than a diagnostic | max_memory_restart: "1G" |
instances + exec_mode | Declare instance count and cluster execution mode in the config, which decides whether zero-downtime reload is available | module.exports = { apps: [{ name: "api", script: "app.js", instances: "max", exec_mode: "cluster" }] } |
error_file / out_file | Pin where logs land so their location is predictable and collectable | error_file: "./logs/err.log", out_file: "./logs/out.log" |
pm2 serve <dir> <port> | Publish a static directory as a service, for front-end artifacts that need no Node logic | pm2 serve ./dist 8080 |
Common pitfalls
SymptomAfter a reboot every process is gone and pm2 list is empty.
Causepm2 startup only prints a command to run; if that line was never executed as the right user the boot unit is not installed, and the list stored by pm2 save has nothing to restore it from.
FixRun pm2 save to store the list, then execute the line that pm2 startup prints, and confirm with pm2 resurrect.
SymptomI edited the config but the old values keep running no matter how often I restart.
CauseThe process still carries its launch-time arguments; the newly added keys were never read. It is also possible the launch used --env and picked up a different section.
FixCheck the effective start command and environment with pm2 describe api, then relaunch from the config with pm2 start ecosystem.config.js --env production.
SymptomThe process restarts by itself after a while and the restart count keeps climbing.
CauseMemory crossed the max_memory_restart ceiling and PM2 restarted it on purpose; the backstop is working, the process did not crash on its own.
FixConfirm with pm2 show api by reading restart count and memory, then hunt the accumulating allocation in code; pm2 reset api clears the counter so it stops polluting the picture.
SymptomThe port is clearly listening locally yet the service is intermittently unreachable.
CauseWith multiple instances started via -i each one tries to bind the same port; the first takes it and the rest restart on the conflict while the list still shows them as present.
FixCheck instance count against port binding, and for multiple instances move to cluster mode via exec_mode: "cluster" in the config, then verify the count in pm2 list.
SymptomLogs filled the disk and the service died.
CauseThe default log files grow without bound; with neither rotation nor cleanup in place, once the disk fills the process can no longer write and falls over.
FixRun pm2 flush to reclaim space, then pm2 install pm2-logrotate for rotation, and pin error_file and out_file in the config when fixed locations matter.
SymptomThe restored process list points at an old code location.
Causepm2 save records the start command and working directory as they were; after the code moved or changed version, resurrect still launches from the recorded path.
FixCheck the paths in pm2 list after restoring, and if they disagree remove the stale entry with pm2 delete api and start again from the current config.
SymptomAuto restart fires constantly and the process never stays up.
CauseThe watch scope includes dependency and log directories, so writing a log or cache at runtime counts as a change and produces a start-write-restart loop.
FixKeep watch: true but state ignore_watch: ["node_modules", "logs"] in the config so triggers land only on real source edits.
SymptomThe pm2 panel opens and immediately exits without showing anything.
CauseThe live panel redraws the screen continuously and cannot render in a non-interactive session or when output is redirected.
FixSwitch to one-shot output: pm2 list for the overview, pm2 show api for one process memory and restart count.
SymptomThe restart count is polluted by an old failure and no longer says whether the current deployment is stable.
CauseThe counter accumulates across the process lifetime, so an early crash stays in it and the number cannot separate history from now.
FixAfter deploying, run pm2 reset api to zero the counter and watch pm2 monit to see whether it climbs again.
Troubleshooting
1List every process and find the rows that are not online
pm2 listScan the status column; rows showing errored or exited are what to investigate next, and the rest can wait.
2Inspect one process in detail to confirm its arguments and restart count
pm2 show apiFocus on restart count, memory and script path: a climbing count points at a crash or a breached limit, while a wrong path means it did not start from the current code.
3Take only the last N log lines to shrink down to the fresh error
pm2 logs api --lines 100The tail is the newest output; if those lines show nothing, widen the window.
4Read only the error stream to gather stack traces in one place
pm2 logs api --errStack traces travel on stderr alongside normal output, and this command separates them out.
5Verify that the launch-time configuration actually took effect
pm2 describe apiCompare script path, exec mode and env in the output against what the config file declares.
6Watch the memory trend to judge whether it leaks slowly
pm2 monitA memory column that only ever climbs and never falls back is the classic leak shape; sampling stops as soon as you leave the panel.
7Truncate the on-disk logs to reclaim disk first
pm2 flushNo output means success; note that history is wiped too, so back it up if you still need it.
8Zero the restart counter after deploying to re-establish a baseline
pm2 reset apiWith the counter back at zero, any later growth in pm2 list is attributable to this deployment.
Command Examples
Start in cluster mode and confirm it is running
pm2 start app.js -i max
pm2 list-i max scales to the core count. pm2 list is the check: status should read online, the instance count should match the core count, and restart:0 confirms nothing has crashed and come back yet.
Output
│ api │ online │ 8 │ 4.2MB │ restart:0 │
Zero-downtime rolling reload after a config change
pm2 reload apiIn cluster mode reload restarts the workers one at a time and keeps the service answering throughout. An app started in fork mode has a single process, where reload degenerates into restart and downtime cannot be avoided.
Enable log rotation to avoid filling the disk
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10MUnbounded logs will eventually fill the disk. After installing the module, lower max_size from its 10M default and keep the daily rotation, which clears old files according to the retention policy.
Output
Modifying value of setting [pm2-logrotate:max_size] with value 10M
Common Pitfalls
- pm2 kill exits the daemon and clears processes — never use kill to "restart PM2" in production; restart the app or the host instead.
- pm2 startup only prints a command; you must actually run that sudo/root line once for boot-start to take effect — a step many people skip.
- reload is zero-downtime only in cluster mode; in fork mode it behaves like restart and drops connections.
- --watch can treat node_modules or logs as restart triggers; always set ignore_watch to avoid useless restart churn.
- pm2 monit is a live panel that stops sampling when you exit; for sustained memory/restart trends use monitoring/alerting rather than watching a terminal.
Tips
- reload is smoother than restart; in cluster mode it restarts one by one (zero downtime); in fork mode reload == restart.
- pm2 save + pm2 startup restores all processes after a reboot.
- For leaks: watch pm2 monit; set max_memory_restart as a safety net.
FAQ
What is the difference between pm2 reload and restart?
restart kills the process and starts it again with a brief downtime; reload in cluster mode cycles workers one by one for zero-downtime updates. Use pm2 reload app for smooth deploys with cluster mode, and restart when you just want to reset a single instance.
pm2 keeps failing with port already in use after restarts — what do I do?
Usually an old process was not fully cleaned up or the port is held elsewhere. Run pm2 delete app to remove the old instance, inspect the port (ss -tlnp on Linux) and kill the holder, verify PORT is free, then pm2 start again. A crash-restart loop can look the same — check pm2 logs for the real exception.
How do I configure pm2 to start on system boot?
Start the apps to persist with pm2 start, run pm2 save to store the list, then run pm2 startup and execute the init command it prints (it generates a systemd or sysv unit). On the next boot PM2 restores the saved apps automatically.
Does pm2 auto-restart crashed processes, and how do I cap memory usage?
A normal crash is restarted by default; set max_restarts to bound repeated retries. To stop a memory leak from exhausting RAM, set --max-memory-restart 1G on start or max_memory_restart in ecosystem.config.js so pm2 restarts above the threshold. Pair it with log rotation for long-lived heavy instances.
What does pm2 save do, and what happens if I skip it?
pm2 save writes the current process list into a dump file, which is required for pm2 startup (boot persistence) and for pm2 resurrect to restore apps. Without it, a reboot or fresh machine loses the managed list and you must pm2 start everything again manually.
Official References
Each command links to its official documentation below, so you can verify the latest usage and read deeper.
Maintained by LaoHand
Publicly updated on Jul 21, 2026, continuously proofread against official docs.
Contact Us
Wrong command or description? Send us corrections, business inquiries or product feedback by email.
Contact Us