Best way to daemonize node.js process in 2021: forever, pm2, nodemon, docker, supervisor, systemd and what to choose

Table of Contents

During my development career I used a lot of different solutions to daemonize processes (mostly, node.js scripts), and I decided to do a quick writeup with very short description of each approach to help fellow developers to choose.

1. Forever

URL: https://github.com/foreversd/forever

Github stars: 13.2k

Pros: super simple and minimal.  

Cons: not active in development. Heavily tied to node.js eco system. README of the project recommends to use pm2 or nodemon.

Conclusion:

This is probably not a good solution for new projects, though it's pure JS and is pretty minimal, which I like.

2. PM2

URL: https://github.com/Unitech/pm2

Github Stars: 34k

Pros:

  • A lot of features.
  • Specializes in Node.js.
  • Zero downtime reload feature is a big one!  

Cons:

  • Big amount if features sometimes mean more cognitive overhead to run when you need super-basic setup, also more moving parts and higher chance that something may break.
  • Is actively monetized so the solution includes paid features.  For example, metrics is a paid feature.
  • Tied to node.js eco system.

Conclusion:  

Jack-of-all-trades. This is a very good solution if you develop only node.js apps, like a lot of features out of the box, and are okay that it way try to monetize on you.

3. Nodemon

URL: https://github.com/remy/nodemon/

Github Stars: 21.8k

Pros:

  • Boring tech: old & proven
  • Unix-like simplicity: does one thing and does it right

Cons:

  • This is not exactly  intended to be used in production.
  • Tied to node.js eco system

Conclusion:

I use nodemon every day, but not for production purposes, since its main purpose is to do reload when you save a file, so your code changes are applied to living process. But I know some developers use if for production as well. I would say you should use it if you develop only node apps and you liked forever.js brutal simplicity.

4. Supervisor

URL: https://github.com/Supervisor/supervisor

Github Stars: 6.6k

Pros:

  • generic: useful not just for node.js - official way to daemonize Laravel queues
  • feature-rich but in a good way - no excess or paid features
  • convenient to use
  • boring tech

Cons:

  • Python (great language but not exactly performant)
  • Not very trendy on Github (because it is boring, right?)

Conclusion:

Supervisor is my current favorite. Mostly because it's generic enough to work with Laravel and node.js processes at the same time, has basic logging out of the box, and has multiple processes setup, too. You don't need big performance for this kind of software, at the same time developer ergonomics of Supervisor is just great. (UPD Aug 2021: my current favorite is now PM2. Read more in the end of the post)

5. Docker

URL: https://github.com/docker

Docker is definitely not a process manager, and is a too big topic for this post, but it solves a lot of things that we used to solve using process managers, in a beautiful way, so take a look at it when you have time (a spare week.. or two).

Pros:

  • Is very powerful and has separate ecosystem
  • Huge momentum: everyone is dockerizing everything now
  • Generic: can daemonize your node.js process or your database

Cons:

  • It is a separate world of complexity and overhead. If you want to quickly prototype and daemonize small JS script this is an overkill

Conclusion:

A lot of people say that PM2 is not needed anymore because of Docker.

I use Docker for a lot of things, but its cognitive overhead is significant. Definitely take a look at it, anyways.

I've spent tens of hours on Docker recently, and I really like the concept, I use it in production pretty successfully, too, but it definitely requires a lot of time and context switching to write Dockerfiles,  build images and test everything - this is getting especially tough when you switch back and forth between 3-4 small projects which quickly evolve. I also don't like the fact that Docker eats a lot of CPU on my fresh Macbook 16" even when it does nothing. VS code remote mitigates this, but not completely, it  is still not perfect for active development.

The main selling point of Docker is that it allows you to build 100% reproducible environment. This is a precious gift when you work in a team, but for sole developer in a side project, this is not always needed, and remember: you have to pay for Docker with your time and context switching, and I felt that it was regularly breaking my flow in smaller projects.

So, I definitely use Docker, but I prefer to use it for other guys projects, to run it on my server, or for my projects which are pretty stable and has multiple developers working on it. In this case, you get all the pros, and almost no cons :)

6. systemd

SystemD is a process manager that you don't need to install (okay, this is true only if you use Ubuntu or Debian - but it is true for me), and it's the best thing about it.

Pros:

  • Is already installed on your droplet
  • Fast

Cons:

  • Developer ergonomics is not perfect: I need to google every time to find out where should I put my systemd init file and how to apply it so it works fine.

I've been using systemd for a few years, but no I am gradually switching back to supervisor, because it is very similar, but is more feature rich, and it provides better developer ergonomics in some parts.  The config file for systemd can be generated via online services like https://mysystemd.talos.sh/ and https://techoverflow.net/2019/03/11/simple-online-systemd-service-generator/

Systemd is a good, generic and minimalistic approach if you work on Linux-based systems without Docker setup, but it was not working perfectly with Laravel multiple workers ( https://github.com/laravel/ideas/issues/1570#issuecomment-475499303 ) so I decided to replace it with Supervisor as my go-to approach.

My approach to daemonizing node.js processes

I try to choose and stick to one process manager on all my new projects, if it is possible, to lessen the cognitive overhead when you log in into some production server and try to quickly debug & restart some process.

Here is what I use currently for all new projects (in 2021):

  • supervisor for production
  • nodemon for development

This was a natural choice because I develop Laravel and Node.js apps.

UPD Aug 2021:

Since I am now doing more and more pure node.js projects, I tend to use pm2 for all the new projects now, instead of supervisorctl. PM2 seems to be more feature-rich and I don't even need to create any files manually to daemonize process - I just do pm2 save after I launched all the processes, so they are safely restarted after machine reboot. It also includes basic stats, which is nice, and monetized features are not obtrusive at all.