Cheat Sheet

PM2 Commands

PM2 is the process manager most Node.js apps run under in production. This sheet covers the pm2 commands for starting and naming apps, reading logs, cluster mode, and making everything survive a reboot with save and startup.

Last updated September 11, 2026

Start Processes

CommandWhat it does
Start a script under PM2 (named after the file)
Start it with a name you can use in every other command
Everything after the bare goes to the script, not PM2
Run under PM2
Any package.json script the same way
Non-Node scripts (bash, python, ruby)
Restart on file changes (development only)
Watch, but not these paths
Restart the process when it passes 300 MB
Flags for Node itself, not the script
Scheduled restart (here 04:00 daily)
Start everything defined in an ecosystem file
Static file server for a build folder, SPA fallback to index.html

More than a couple of flags belongs in an ecosystem file rather than your shell history; the PM2 ecosystem generator writes one from a form.

List and Status

CommandWhat it does
Every process with status, CPU, memory and restart count ( and are the same)
Full detail for one process: paths, logs, env, uptime ( is the same)
The list as JSON, for scripts
The same JSON, readable
Check the PM2 daemon is up
Full diagnostic dump for a bug report

The restart counter ( in the list) climbing on its own means the app is crash-looping; read the error log before anything else.

Logs

PM2 captures each process's stdout and stderr to files under .

CommandWhat it does
Stream all logs live, like for everything
Only one process
Start with the last 200 lines instead of 15
Error stream only ( for stdout only)
Structured output, one JSON object per line
Prefix each line with a timestamp
Empty every log file ( for one)
Log rotation module; without it the files grow forever
Rotate when a file passes 10 MB
Keep 14 rotated files
Gzip rotated files

PM2 does not rotate logs on its own, and a chatty app fills a disk quietly. Install on every server the first time you set one up.

Restart, Reload and Stop

CommandWhat it does
Kill and start again; drops requests in flight
Every process
Zero-downtime restart, one instance at a time (cluster mode only; falls back to restart in fork mode)
Restart and pick up the current shell environment
Stop it but keep it in the list, so brings it back
Stop everything
Stop it and remove it from the list
Empty the list
Stop the PM2 daemon and every process it manages

keeps the entry (status ); forgets it. After any change you want back after a reboot, run again.

Cluster Mode

Cluster mode runs several instances of the same Node app behind PM2's built-in load balancer, one per core with . The app needs no code changes as long as it does not keep local state.

CommandWhat it does
One instance per CPU core
Exactly four instances
All cores but one
Resize a running cluster to 8 instances
Add two instances
Roll through the instances with zero downtime

Cluster mode is Node-only, since it uses the Node module. Sticky sessions and anything held in process memory (in-memory sessions, local caches) break across instances; move that state to Redis or the database first.

Save, Startup and Resurrect

Surviving a reboot is a two-step dance, and skipping the second step is the classic mistake.

CommandWhat it does
Detect the init system and print the install command; it does nothing else
(paste the printed command)The line it printed; this installs the boot hook
Write the current process list to ; this is what boot restores
Save even when the list is empty
Restore the saved list by hand, without rebooting
Remove the boot hook
Delete the saved list

So the full sequence is: , run the command it printed, get your apps running the way you want, then . The hook restores whatever the last captured, so rerun it after adding, deleting or renaming processes.

Windows

only knows Linux and macOS init systems. On Windows it prints nothing useful, so PM2 has to be installed as a Windows service instead.

CommandWhat it does
Same install; lands in npm's global bin folder
Community helper that registers the boot hook
Install the hook, then as usual
Same streaming; the files live under

The other option is , which registers PM2 itself as a Windows service so it starts before anyone logs in. Either way is still what decides which apps come back. Everything else (, , , , ecosystem files) behaves the same; paths in an ecosystem file want forward slashes or escaped backslashes.

Environment Variables

CommandWhat it does
Environment from the shell, captured at start
Use the block from the ecosystem file
Re-read the shell environment; a plain restart keeps the old one
Print the environment of process id 0

PM2 snapshots the environment when a process first starts and reuses it on every restart. Changing a variable in the shell or in does nothing until you restart with or delete and start fresh. This surprises everyone once.

Node Version and Interpreter

The PM2 daemon keeps the Node version it was started with. Switching versions with nvm changes your shell, not the daemon, so apps keep running on the old binary until you reload the daemon.

CommandWhat it does
Shows the interpreter path and Node version for one process
Shows the Node version the PM2 daemon itself runs on
Reload the daemon on the current Node and bring processes back
Use whatever is first on PATH
Pin one app to an exact Node build
Run TypeScript directly (install yourself first)
A compiled binary needs no interpreter

In an ecosystem file the same settings are the and fields, which is the sane place to pin a version per app:

{
  name: "api",
  script: "./server.js",
  interpreter: "/home/deploy/.nvm/versions/node/v22.11.0/bin/node",
}

After an nvm upgrade, is only half the job: the boot hook installed by has the old PATH written into it, so run , , the command it prints, then again. PM2 no longer bundles , so TypeScript needs (or a local install plus ); compiling to JavaScript first and running the output is steadier in production.

Ecosystem File

holds everything the start flags express, in a file you can commit. writes a sample, or the PM2 ecosystem generator builds one from a form.

module.exports = {
  apps: [{
    name: "api",
    script: "./server.js",
    instances: "max",
    exec_mode: "cluster",
    max_memory_restart: "300M",
    args: "--port 3000",
    env: { NODE_ENV: "development" },
    env_production: { NODE_ENV: "production" },
  }],
};
CommandWhat it does
Start every app in the file
Just one of them
Apply the block
Reload everything the file defines
Restart and re-read the file's env blocks

Monitoring

CommandWhat it does
Live dashboard in the terminal: CPU, memory and logs per process
Uptime, restart count, log paths, script path for one process
The quick overview; watch the memory and columns

is the fastest answer to "which process is eating the CPU". For alerting and history, PM2's hosted monitoring () exists, but plain over SSH covers day-to-day checks.

Install and Upgrade

CommandWhat it does
Install PM2 globally; the binary goes in npm's global bin
Print that global prefix when the shell cannot find
Check the installed version
Reload the PM2 daemon in place after upgrading pm2 itself, keeping processes alive
The full upgrade sequence
Install a PM2 module (log rotation, metrics)

Upgrading the npm package alone changes nothing for running apps, since the old daemon stays in memory. is what swaps it. Under nvm, PM2 is installed per Node version, so a new Node version means installing PM2 again.

Deployment

CommandWhat it does
First-time setup of the deploy target defined in the ecosystem file
Pull, install and reload on the target servers

reads a section in the ecosystem file (host, repo, path, post-deploy command) and works fine for simple git-based deploys. Teams that outgrow it usually move to CI plus over SSH.

If you would rather have the init system own the process, with proper dependencies and journald logging, the pm2 to systemd converter turns an ecosystem file into unit files, and the systemctl cheat sheet covers managing them.

Gotchas

  • alone does nothing at boot. It prints a command; run that command, then . The saved dump is what gets restored, so save again after every change to the list.
  • is only zero-downtime in cluster mode with two or more instances. In fork mode it is just a restart with a friendlier name.
  • Restarts keep the environment from the first start. New or changed variables need , or a delete and a fresh start.
  • Logs are never rotated by default. before the disk fills, and when it already has.
  • in production causes restart loops when the app writes into its own directory (logs, uploads). Use , or better, no watch at all outside development.
  • in cron, CI or GitHub Actions usually means npm's global bin is not on that context's PATH; use the absolute path to the binary.
  • Switching Node with nvm does not move the apps. The daemon holds the old version until , and the boot hook holds the old PATH until you rerun and .
  • takes down the daemon and every app with it. To remove one app, .

PM2 FAQ

How do I make PM2 start on boot?

Two commands, and people routinely stop after the first. pm2 startup does not enable anything itself: it detects your init system and prints a command, usually starting with sudo env PATH=..., which you copy, paste and run once to install the boot hook. Then pm2 save writes the list of processes currently running to ~/.pm2/dump.pm2, and that file is what gets restored at boot. Skip pm2 save and the server comes back up running nothing. Rerun pm2 save whenever the process list changes, and pm2 unstartup removes the hook. On Windows pm2 startup does nothing at all, since there is no init system for it to detect; install PM2 as a service with pm2-installer instead, then pm2 save as usual. If you would rather let systemd own the app directly, the pm2 to systemd converter on this site turns an ecosystem file into unit files.

How do I check which Node version PM2 is using?

pm2 describe api prints the interpreter path and Node version for one process, and pm2 report shows the version the PM2 daemon itself is running. They can disagree, and that is the whole problem: the daemon keeps the node that was on PATH when it first started, so after nvm install 22 your apps carry on with the old binary no matter how many times you restart them. pm2 update fixes it by reloading the daemon in place on the current node and bringing the processes back. Two follow-ups get missed. The boot hook from pm2 startup has the old PATH baked into it, so rerun pm2 unstartup, pm2 startup and pm2 save after switching versions. And when different apps need different versions, pin each one with --interpreter and an absolute path to that node binary.

How do I stop a PM2 process for good?

pm2 stop api halts the process but keeps the entry, so it still appears in pm2 list as stopped and pm2 restart api brings it back. pm2 delete api removes the entry. pm2 kill stops the daemon and everything under it. The step people forget is pm2 save: the boot hook restores whatever the last save captured, so anything you stopped or deleted is back after the next reboot unless you save again. If a process starts up again the moment you stop it, check pm2 list for a duplicate entry under a different name, and check whether it was started with --watch and something is writing into its directory.

How do I run npm start with PM2?

Point PM2 at the npm binary and pass the script name after a double dash: pm2 start npm --name web -- start. Everything after the bare -- goes to npm, so pm2 start npm --name web -- run dev runs npm run dev the same way. This works but adds an npm process in front of node, so for production the cleaner move is to check what npm start actually runs in package.json and start that file directly: pm2 start ./server.js --name web. For scripts that need build tools or watchers, keep them out of PM2 entirely and reserve it for the long-running server.

Is PM2 only for Node?

No. --interpreter runs anything with a shebang or a runtime: pm2 start app.py --interpreter python3, pm2 start run.sh --interpreter bash, pm2 start app.rb --interpreter ruby. Restarts, logs, monitoring and boot persistence all work the same. Compiled binaries need no interpreter at all: pm2 start ./mybinary --name svc. What is Node-only is cluster mode, because -i uses Node's own cluster module to share one listening socket between instances. For a Python or Ruby service, run several named copies on different ports behind nginx, or use that runtime's worker model (gunicorn, puma) and let PM2 supervise the one master process.

Related cheat sheets