PM2 and auto-restart: keeping your process alive

PM2 is a Node.js process manager that restarts your app when it exits or crashes. Run pm2 start app.js, then pm2 save and pm2 startup so it survives a reboot.

Updated 4 min read

Learning objectives

After reading this article you will be able to:

  • Start an app with PM2 and configure automatic restarts
  • Limit memory use and crash loops with max_memory_restart and max_restarts
  • Know when to use pm2-runtime in a container or skip PM2 entirely
On this page

A Node.js process that throws an unhandled exception simply dies. If nothing starts it again, your bot, API or site stays down until someone notices. A process manager fixes that: it watches your app and restarts it when it goes down. In the Node.js ecosystem, the most widely used one is PM2.

pm2 startonlinecrashesrestart_delayrestarts…erroredstops tryingmax_restarts: 16consecutive unstable restartstime
PM2 brings a crashed process back, but after 16 consecutive unstable restarts it marks the app as errored and gives up.

How do you install PM2 and start an app?#

With Node.js installed (see how to host a Node.js app), install it globally and start your main file:

bash
npm install pm2 -g
pm2 start app.js --name my-app
pm2 list
pm2 logs my-app

pm2 list shows each process and its status, pm2 logs streams output in real time, and pm2 restart my-app restarts manually. Use pm2 stop my-app and pm2 delete my-app to stop it and remove it from the list.

autorestart is true by default: if the app crashes or exits, PM2 starts it again. For a one-off script (a migration, for example), turn it off with --no-autorestart.

How do you use an ecosystem file?#

Command-line flags don't scale. An ecosystem file keeps all the configuration in one versioned file:

js
// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: "my-app",
      script: "./app.js",
      max_memory_restart: "300M",
      max_restarts: 10,
      restart_delay: 3000,
      kill_timeout: 5000,
      env: { NODE_ENV: "development" },
      env_production: { NODE_ENV: "production" },
    },
  ],
};

Start it with pm2 start ecosystem.config.js --env production. The env_production block applies only when you pass --env production. Never store secrets (tokens, passwords) in this file: read them from environment variables. The file uses CommonJS (module.exports); if your package.json has "type": "module", name it ecosystem.config.cjs.

Which restart options are worth using?#

Option What it does
autorestart Restarts when the process exits. Default: true.
max_memory_restart Restarts when memory passes the limit ("300M", "1G"). PM2 checks every 30 seconds.
restart_delay Milliseconds to wait before restarting a crashed app. Default: 0.
exp_backoff_restart_delay Grows the delay after each crash, up to 15 seconds. Resets to 0 after 30 seconds of stable uptime.
max_restarts Consecutive unstable restarts before PM2 gives up. Default: 16.
min_uptime Minimum lifetime for the app to count as started.
cron_restart Scheduled restart, for example "0 4 * * *" for 4 AM daily.
stop_exit_codes Exit codes that don't trigger a restart ([0]).

Two of these need care.

max_memory_restart hides a memory leak; it doesn't fix it. It is a useful stopgap while you investigate. If the app restarts every hour because of memory, the bug is still in your code.

Without restart_delay, a startup error becomes a tight loop. The app dies in milliseconds, PM2 starts it, it dies again. After max_restarts consecutive unstable restarts, PM2 marks the app errored and stops trying. Use restart_delay or exp_backoff_restart_delay to give external dependencies, such as a database that is still booting, some breathing room.

Does PM2 start on its own after the server reboots?#

Not unless you ask. It takes two commands:

bash
pm2 startup
pm2 save

pm2 startup detects your init system (systemd, for example) and prints the command that registers PM2 at boot: copy it and run it (with sudo) before pm2 save. pm2 save stores the current app list, and PM2 restores it when the server comes up. To restore manually, use pm2 resurrect. After upgrading Node.js, run pm2 unstartup and then pm2 startup again so the service points at the new binary.

How do you use PM2 inside Docker?#

In a container (see what is Docker), use pm2-runtime, a drop-in replacement for the node binary that runs in the foreground, as a container expects:

dockerfile
FROM node:lts
WORKDIR /app
COPY . .
RUN npm install
RUN npm install pm2 -g
CMD ["pm2-runtime", "ecosystem.config.js"]

PM2 forwards shutdown signals to your app. Listen for SIGINT to close connections before exiting: PM2 waits 1600 ms by default before SIGKILL, adjustable with kill_timeout. For one process per container, add --only your-app-name.

In most cases, though, PM2 inside Docker is redundant: the container's own restart policy already recreates a dead process.

When can you skip PM2?#

PM2 makes sense when you administer the machine yourself, as on a VPS. If the platform already restarts a stopped process, PM2 is one more layer to maintain. An orchestrated container, a systemd service with Restart=always, or a host with automatic restarts all do the same job.

Keep in mind that PM2 only recreates the process: it doesn't fix the bug that took the app down. Log your errors and read the logs (see how to read app logs) to find the cause.

How to do this on Square Cloud#

On Square Cloud, you don't need PM2, and it isn't recommended. Containers are always on, with no sleep mode. Automatic restart is available on every plan and comes on when you deploy from the dashboard (in a hand-written squarecloud.app, set AUTORESTART=true): it brings back a process that exits with an error.

You deploy with a ZIP upload, the CLI, GitHub or the VS Code extension. If the app needs configuration, set environment variables in the dashboard: the change applies on the next restart, with no rebuild. Logs appear in real time in the dashboard and the CLI, which helps you find why an app went down.

One caveat: the automatic restart recreates the process, but it doesn't fix a code error or a memory leak. If the app exceeds its allocated RAM, it stops and stays stopped: raise the memory in the settings, start it again and investigate the cause. To see how this fits a bot, read how to keep a Discord bot online 24/7.

See what the hosting includes in Features.

Deploy

Push from GitHub, the CLI or a ZIP and go live in seconds

Learn more

FAQs

Does PM2 restart my app automatically if it crashes?

Yes. autorestart is on by default, so PM2 starts the process again when it fails or exits. For one-off scripts, pass --no-autorestart.

How do I make PM2 start when the server boots?

Run pm2 startup and execute the command it prints with sudo. Then, with your apps running, run pm2 save to store the list PM2 restores at boot.

Do I need PM2 inside a Docker container?

Usually not. The container restart policy or the orchestrator already recreates a dead process. If you want PM2 there, use pm2-runtime, which runs in the foreground.

Why is my app stuck in the errored state in PM2?

PM2 gives up after 16 consecutive unstable restarts (max_restarts). Check pm2 logs, fix the cause, then start it again with pm2 restart.

Next articleWhat is CI/CD?CI/CD is the practice of testing every code change automatically (CI) and shipping it to production without manual steps (CD). See how a pipeline works.

More in Deploy

See all 33 articles