How to Configure PM2 the right way

mr_ali3n

Vaibhav Mehta

Posted on November 8, 2022

How to Configure PM2 the right way

Prelude

While developing apps on NodeJS, you must have used packages like Nodemon, which monitors your code for changes and restarts your Node App. Though Nodemon is super useful in development, it's not recommended to use it in Production. Nodemon is not something you use if you wish to keep your app alive on Production if it crashes.

Here's where PM2 comes in handy. I've been hosting my NodeJS apps using PM2 on production as well I use PM2 for Development.

Quoting from PM2:

PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime, and to facilitate common system admin tasks.

Before we go ahead and configure the PM2, yes, PM2 does support the auto-reload feature like Nodemon using the watch feature. More on this later in the article.


Configuring PM2

PM2 simplifies the way you could define the configuration for your app using PM2 ecosystem configuration file. You could use a PM2 configuration file for configuring multiple envs, logging, etc.

Here's a snippet for configuring your PM2 envs and I'll brief each of these later in the article.

ecosystem.config.js

module.exports = {
  apps: [
    {
      name: "PROJECT_NAME",
      script: "./server.js",
      instances: 2,
      max_memory_restart: "300M",

      // Logging
      out_file: "./out.log",
      error_file: "./error.log",
      merge_logs: true,
      log_date_format: "DD-MM HH:mm:ss Z",
      log_type: "json",

      // Env Specific Config
      env_production: {
        NODE_ENV: "production",
        PORT: 8080,
        exec_mode: "cluster_mode",
      },
      env_development: {
        NODE_ENV: "development",
        PORT: 8080,
        watch: true,
        watch_delay: 3000,
        ignore_watch: [
          "./node_modules",
          "./app/views",
          "./public",
          "./.DS_Store",
          "./package.json",
          "./yarn.lock",
          "./samples",
          "./src"
        ],
      },
    },
  ],
};
Enter fullscreen mode Exit fullscreen mode

You can put the configuration file at the root level of your project.


Basic Configuration

  1. name

    This could be your project name and PM2 will use this name to name your workers.

  2. script

    The entry point of your app, mostly it's the server.js. Make sure you set the right path, the above configuration assumes that you've the ecosystem.config.js and the server.js file at the root level of your project.

  3. instances

    This is the number of workers you wish to spawn.

  4. max_memory_restart

    PM2 allows you to reload your application based on the memory limit you specify using the max_memory_restart.


Logging Configuration

  1. out_file

    Generic logging, all your console.log() statements are logging in this file along with other information.

  2. error_file

    Similar to out_file but error files only log the errors of your application.

  3. merge_logs

    This is not needed if you are fine with PM2 storing a unique log file for each of its PID - Process ID). Using this config will merge all your app logs into a single file. merge_logs will merge your log files of various PIDs and it doesn't merge the output and error logs into one.

  4. log_date_format

    The above is self-explanatory. You could define a date/time format you wish to print your logs in.

  5. log_type

    Specify the output style, it's raw by default but we are using JSON here.

Logs Path & Disabling Logs
By default, your Logs are stored under $HOME/.pm2/logs/<app name>-(out||error)-<pid>.log. You could disable logging by pointing the log path to out_file: "/dev/null" and the same is applicable for error_file


Environment specific Configuration

  1. env_production && env_development

    These are nothing but different environments you wish to run your apps in, using PM2. You could create config for multiple staging env if your setup requires to do so.
    • NODE_ENV
      The above set the env variable value to Production / Development for your app.
    • PORT
      Port at which you would like to initiate your app at.
  2. exec_mode

    You could use cluster or fork, where the latter is the default mode. It is recommended to use the cluster mode on production and you could use a single instance locally. Number specified in the instances creates child processes (workers) and distributes the incoming connections across the worker processes. You could set the value to 0 or max to specify how many workers you wish the PM2 should launch (max will spawn as many workers as the number of available cores). From PM2 Docs
    The worker processes are spawned using the child_process.fork() method, so that they can communicate with the parent via IPC and pass server handles back and forth.
  3. watch

    We need to use this only on the dev envs. The use case is exactly what nodemon does. The watch monitors the file changes in your app and restarts your app as soon as a file change is detected.
  4. watch_delay

    You don't want to end up restarting your app as soon as you save your file. So if you try to save your file multiple times in under three seconds, it will only restart your app once as it will clear the watch timer every time you save your files under three seconds.
  5. ignore_watch

    There will your app will end up restarting even if you install an NPM package, add or move a file in your app dir, or as simple as add an img in your public dir. Hence, any folder or file paths added to the ignore_watch array will not trigger a restart of your app as they are not relevant and don't require your app to be restarted in the first place.

Useful PM2 commands

Starting your App in Dev & Production mode

You could add the following commands to package.json

"scripts": {
  "start_dev": "pm2 start ecosystem.config.js --env development",
  "start_prod": "pm2 start ecosystem.config.js --env production"
},
Enter fullscreen mode Exit fullscreen mode

You could execute the above commands like npm run start_dev and npm run start_prod which starts your app in dev and production mode with the given config.


Start, Stop, Restart & Kill your App

Kill your App
pm2 kill #kills all pm2 workers
Enter fullscreen mode Exit fullscreen mode
Reloading your App
pm2 reload all
Enter fullscreen mode Exit fullscreen mode
Restarting your App
pm2 restart all
Enter fullscreen mode Exit fullscreen mode

Alternatively, you could pass the PID instead of using all keyword which will end up running the same operation on all the processes.

Restarting a process will kill and restart it as opposed to reloading which achieves a 0-second-downtime reload.


Logs

Delete all Logs
pm2 flush
Enter fullscreen mode Exit fullscreen mode
Read Logs
pm2 logs
Enter fullscreen mode Exit fullscreen mode

Processes

List Processes
pm2 list
Enter fullscreen mode Exit fullscreen mode
Monitor Processes
pm2 monit
Enter fullscreen mode Exit fullscreen mode

References

You could also configure the deployment process using the PM2 but I've not covered it in the above tutorial as I've never used it personally.

Here are some resources which will help you understand PM2 configuration in detail.

💖 💪 🙅 🚩
mr_ali3n
Vaibhav Mehta

Posted on November 8, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related