A Complete Guide - Pm2 Process Manager

A Complete Guide - Pm2 Process Manager

Everything you need to know about Pm2 process manager with Node.JS

Introduction

If you're familiar with Node.js and looking to optimize your deployment workflow, this guide will walk you through the basics of PM2, a powerful process manager for Node.js applications. PM2 helps ensure high availability, efficient performance, and easy management of Node.js processes.

1. Basics of PM2

1.1 What is Process Manager

Everyone knows about npm, it is used for package management with Node Js. And NPM provides the ability to start the application.

The “npm start” (which is the “npm run start” alias) is performed if NPM is chosen as a value for the PROCESS_MANAGER variable on the NodeJS container. As a result, the script defined in “start” of package.json is launched.

Running locally with npm has no issue but when it comes to deployment to server weather it's your dev, stage, or prod server you need to

  • Restart the app automatically if it crashes.

  • Gain insights into runtime performance and resource consumption.

  • Modify settings dynamically to improve performance.

  • Control clustering. (If server support multi core ... later in article)

In short help in deployment and make sure high availability of application. This is what exactly PM2 will do.

1.2 PM2 - Getting Started in 5 min

Install

npm install pm2@latest -g

Open any NodeJs App in terminal - In this case app.js is start point of my app.

pm2 start app.js

# Or Specify an app name
pm2 start app.js --name <app_name>

List all running app

Restart app

Any change you make to app will not reflect until you not restart.

In pm2 there are one more option to do same thing with different flow. That is ...

Reload app

Basic difference between pm2 restart and pm2 reload is as opposed to restart, which kills and restarts the process, reload achieves a 0-second-downtime reload. With reload, pm2 restarts all processes one by one, always keeping at least one process running.

Stop app

To stop any working process in list In this case I passed 0 which is the id of process retunning. You can perform any action in this list with id | app_name | file name.

Delete app

If you want to delete app from the list then

View Logs of all or selected app

 #View all logs
pm2 log 

# View selected app
pm2 log --name app
#or
pm2 log 0

What is the default location of PM2 log files?

pm2 saves logs to $HOME/.pm2/logs/XXX-err.log by default, where XXX is your pm2 app name.

Monitor app performance

pm2 monit

Auto restart apps on file change

PM2 can automatically restart your application when a file is modified in the current directory or its subdirectories. This will do same like nodemon used for local development running.

pm2 start app.js --watch

2. Fork Mode vs Cluster Mode

pm2 can run your applications in different modes, including Fork mode and Cluster mode. Here's a brief overview of each:

2.1 Fork Mode

  • In Fork mode, each application instance runs as a separate process.

  • This is the default mode for pm2.

  • If you start an application with pm2 start app.js, it will run in Fork mode by default.

  • It's suitable for applications that don't take advantage of multiple CPU cores since each process is independent.

2.2 Cluster Mode

  • In Cluster mode, pm2 uses `Node.js` built-in cluster module to create a cluster of processes to take advantage of multiple CPU cores.

  • This mode is useful for applications that can benefit from parallel processing on multiple cores.

  • It enables load balancing among the different worker processes.

  • The master process manages the worker processes, and if one of them dies, pm2 restarts it.

max - denote maximum number of instances that is possible on machine. If your machine is 6 Core then its max value. You can pass any number also.

pm2 start app.js -i 2

3. Best practices when working with node

3.1 Install PM2 Globally

Install PM2 globally on your server or development machine to make it available system-wide:

npm install -g pm2

3.2 Automatic Restart: after server reboot

Enable automatic restart for your applications to ensure they restart in case of a failure. This helps improve the reliability of your services.

pm2 startup
pm2 save

3.3 Graceful Shutdown

Configure your applications to handle graceful shutdowns. PM2 can send a SIGINT signal to gracefully stop your application. Handle this signal in your code to perform cleanup operations

process.on('SIGINT', function () {
    // Cleanup code here
    process.exit(0);
});

3.4 Environment Variables

Use PM2's support for environment variables.

# --env is avaliable in restart also
pm2 start your-app.js --env production

4. Advance Config - Manage Microservices

If you have multiple applications (or micro servies) to manage, consider using a process file to define configurations for each application. This makes it easier to manage and scale your deployments.

Below command will generate ecosystem.config.js in your current folder.


pm2 init app
module.exports = {
  apps : [{
    script: 'index.js',
    watch: '.'
  }, {
    script: './service-worker/',
    watch: ['./service-worker']
  }],

  deploy : {
    production : {
      user : 'SSH_USERNAME',
      host : 'SSH_HOSTMACHINE',
      ref  : 'origin/master',
      repo : 'GIT_REPOSITORY',
      path : 'DESTINATION_PATH',
      'pre-deploy-local': '',
      'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
      'pre-setup': ''
    }
  }
};

You can edit it or create based on your project structure. If you are creating your own configuration file, make sure it ends with .config.js so PM2 is able to recognize it as a configuration file.

module.exports = {
  apps : [{
    script: 'auth/app.js',
    watch: '.'
  }, {
    script: 'inventory/app.js',
    watch: '.'
  }]
};

Run app using config

pm2 start ecosystem.config.js

Main Pm2 documentation has Complete detail on all advance flag you can set in config like number of instances, which file watch for change etc..

Deployment

when you want to deploy applications on a baremetal server in one or many servers at once.

module.exports = {
  apps : [{
    script: 'api.js',
  }, {
    script: 'worker.js'
  }],

  // Deployment Configuration
  deploy : {
    production : {
       "user" : "ubuntu",
       "host" : ["192.168.0.13", "192.168.0.14", "192.168.0.15"],
       "ref"  : "origin/master",
       "repo" : "git@github.com:Username/repository.git",
       "path" : "/var/www/my-repository",
       "post-deploy" : "npm install"
    }
  }
};

Specifying SSH keys

You just have to add the “key” attribute with path to the public key, see below example :


"production" : {
  "key"  : "/path/to/some.pem", // path to the public key to authenticate
  "user" : "node",              // user used to authenticate
  "host" : "212.83.163.1",      // where to connect
  "ref"  : "origin/master",
  "repo" : "git@github.com:Username/repository.git",
  "path" : "/var/www/my-repositor",
  "post-deploy" : "npm install & pm2 startOrRestart ecosystem.json --env production"
}

Before running deployment make sure:

  • Remote servers have PM2 installed

  • Remote servers have granted permissions to GIT clone the target repository

To deploy on server you need to setup once

pm2 deploy production setup

then

pm2 deploy production

5. Cron - Setup

Let's say one of your micro-service is related to send notifications to users at specific time. And you want to trigger it. ecosystem.config.js add one more entry for cron job

module.exports = {
  /**
   * Application configuration section
   * http://pm2.keymetrics.io/docs/usage/application-declaration/
   */
  apps: [
    ...
    {
      name: 'Cron Job',
      script: "crons/cronjob.js",
      instances: 1,
      exec_mode: 'fork',
      cron_restart: "0,30 * * * *",
      watch: false,
      autorestart: false
    }
  ]
};
  • Cron Expession - cron_restart: "0,30 * * * *" -> "At minute 0 and 30"

  • autorestart: false important because otherwise pm2 will restart the cron after completion immediately

  • make sure instances - 1 otherwise multiple cron processes will run.

pm2 start crons/cronjob.js --no-autorestart --instances 1  --cron "0,30 * * * *"

6. Bonus Tip ✨

Logrotate

PM2 module to automatically rotate logs of processes managed by PM2.

Log rotation is the process of controlling the size of log files. When an existing log file reaches a certain threshold—usually a maximum file size, age, or number of records—the associated application will rename it, create a new file with the original name, and continue writing events to the new file.

pm2 install pm2-logrotate
OptionDefault ValueDescription
max_size10M(e.g., 10G, 10M, 10K).
retain30 file logsThe number of rotated logs to retain. If set to 7, for example, at most 7 rotated logs and the current one will be kept.
compressfalseEnable compression via gzip for all rotated logs.
dateFormatYYYY-MM-DD_HH-mm-ssFormat of the data used to name the log files.
rotateModuletrueRotate the log of pm2's module like other apps.
workerInterval30 secsInterval at which the worker checks the log's size (minimum is 1 second).
rotateInterval0 0 * * * everyday at midnightCron expression used to force rotation when executed. It follows the node-schedule format, allowing all valid cron expressions for node-schedule.
TZSystem timeStandard tz database timezone used to offset the log file saved. For example, a value of Etc/GMT+1 with an hourly log will save a file at hour 14 GMT with hour 13 (GMT+1) in the log name.
pm2 set pm2-logrotate:max_size 1K
pm2 set pm2-logrotate:rotateInterval '*/1 * * * *' (force rotate every minute)

Thank-you for reading 🙂

Main website - https://www.priya.today/