May 25, 2023

Manage Your Node.js Application in Production with PM2

Manage Your Node.js Application in Production with PM2

When in production, a Node.js server must be able to automatically restart in the eventuality of a crash or a machine reboot.

It must also be able to reload upon code change with a minimal amount of downtime.

As the server cannot perform these tasks itself, we need to delegate them to a special type of program called a process manager, whose primary job is to keep the application alive forever.

In this article, you’ll learn how to use the PM2 process manager to start, stop, restart, and reload your Node.js applications when in production.

Getting started with PM2

Just like when using Docker, the applications managed by PM2 can be started, listed, and stopped.

Installation

To install the PM2 command-line tool, you can use the following npm install command:

$ npm install -g pm2

That will install this package globally, so it can be used in any of your projects.

Starting an application

To start an application in production mode, you can use the pm2 start command, that will daemonize (i.e. run as a background task), monitor, and keep it running forever.

$ pm2 start app.js

Alternatively, you can use the --name option flag to give that process a more explicit name that will make it easier to manage in the future.

$ pm2 start app.js --name <app>

Listing running applications

To list all the processes managed by PM2, as well as additional information such as their uptime, status, CPU usage, memory usage, and so on, you can use the pm2 list command.

$ pm2 list

Stopping running applications

To stop a running application managed by PM2, you can use the pm2 stop command, that will send a SIGINT signal to your application.

$ pm2 stop <app>

To allow a graceful shutdown, make sure you intercept the SIGINT signal and clear all the ressources used by your application (i.e. database connections, processing jobs, etc) before it terminates.

process.on('SIGINT', () => {
  // close database connection
  // terminate background jobs
  // ...
});

Note that the SIGINT signal can be replaced by any other signal using the PM2_KILL_SIGNAL environment variable.

Also note that, by default, PM2 will await for 1.6s before sending another uncatchable SIGKILL signal to force the process exit.

Restarting strategies

Over time, it will happen that a process needs to be restarted due to an abnormal consumptions of resources, updates in the source code, repeated errors that need to be fixed, and so on.

When a process terminates the PM2 daemon will automatically try to restart it.

In some cases, it can be useful to define the conditions under which these processes should be restarted, or in certain cases, not restarted at all, in order to preserve the system’s resources.

Here is a short list of the most useful options provided by PM2 to delimit the boundaries of these restarts.

Manual restart

To manually restart a running process — which implies killing it first — you can use the pm2 restart command:

$ pm2 restart <app>

Restart on file change

As with Nodemon, you can configure PM2 to automatically restart an application by watching for file changes within the directory and subdirectories of the launch script using the --watch option flag:

$ pm2 start app.js --watch

Which can also be combined with the --ignore-watch option flag:

$ pm2 start app.js --watch --ignore-watch "node_modules"

You can learn more about the Nodemon utility by reading our article on how to automatically restart your node.js application on file change in development mode.

Restart on memory threshold

The --max-memory-restart option flag allows you to restart an application whenever it reaches a certain memory threshold, which can help prevent a heap out of memory error, if for example the server it runs on has a limited amount of memory, like a small EC2 instance.

$ pm2 start app.js --max-memory-restart 100M

Restart with a delay

The --restart-delay option flag allows you to wait for a certain amount of milliseconds between restarts, which can help reduce the pressure on the database or external providers.

$ pm2 start app.js --restart-delay 3000

Restart N times

The --max-restarts option flag allows you to determine how many times PM2 should restart the application, preventing it from entering an infinite crash loop.

$ pm2 start app.js --max-restarts 3

Reloading with 0s downtime

As opposed to a restart, PM2 offers the possibility to reload your application with 0s downtime using the pm2 reload command:

$ pm2 reload <app>

Note that when using this command, PM2 will start a new instance of your application before shutting down the previous one, which will cause a temporary increase in memory and resources usage.

Related posts