Upgrading Node under pm2 without the surprises
TL;DR: When upgrading Node.js with nvm under pm2, pin nvm alias default to a major version, update the saved PATH in ~/.pm2/dump.pm2 for fork-mode apps, regenerate the pm2 systemd unit with the new node binary, and check readlink /proc/PID/exe before uninstalling the old version.
A security release came out, so I moved a few pm2 apps to a newer Node with nvm. nvm install took a minute. Finding every place the old version was still hiding took longer. Here is the order that worked with one restart per app.
1. Pin the nvm default to a major version
If your default is lts/*, nvm rewrites that alias every time it fetches the remote list. When a new line goes LTS, default points at a version you never installed, and new shells start with no node at all.
nvm install 24 --reinstall-packages-from=22
nvm alias default 24
--reinstall-packages-from reinstalls the same pm2 version you had, not the latest one. That's what you want here.
2. Fork-mode apps remember the old PATH
pm2 saves each app's environment in ~/.pm2/dump.pm2. Fork-mode apps spawn node through the saved PATH, so after a daemon restart they quietly keep running the old binary. Cluster-mode apps follow the daemon's own node.
Back up the dump, then replace the old version string in PATH, NVM_BIN, NVM_INC and _. pm2 restart --update-env also works, but run from a non-interactive SSH command it picks up that shell's thinner PATH.
3. Regenerate the systemd unit
The unit made by pm2 startup hard-codes the node path. Generate it again with the new binary:
NEW=$HOME/.nvm/versions/node/v24.x.y
sudo env PATH=$NEW/bin:$PATH $NEW/bin/node $NEW/lib/node_modules/pm2/bin/pm2 \
startup systemd -u $USER --hp $HOME
sudo systemctl daemon-reload
sudo systemctl restart pm2-$USER
Avoid pm2 update over SSH for this. It restarts the daemon inside your SSH session's scope instead of under systemd.
4. Verify, then uninstall
for p in $(pgrep -f node); do readlink /proc/$p/exe; done | sort | uniq -c
pm2 save
Only when nothing points at the old version, run nvm uninstall.