If you have been using Node.js for sometime, you should know that it is single threaded. This is why you can’t take full advantage of multiple core machines unless you use the cluster module or a process manager like PM2.

I’m working on an application that used the cluster module for managing processes. Although, there were some benefits to this, I decided to move from the cluster module to PM2 & RabbitMQ. This blog will cover the reasons why I made this change and provide background on how and why I moved to PM2 & RabbitMQ.

The Cluster module:

The cluster module in Node.js allows easy creation of child processes that all share server ports. I was using the cluster module to

Run multiple processes of the app itself.

Manage multiple child_processes for separate tasks like sending SMS, emails, notifications.

In the code above, there is only one master in the cluster, I get one child process for each worker:

1 smsWorker + 1 emailWorker + 1 notifWorker + numCPUs app processes.

With this implementation, I had to also manage the state of the worker process. If it goes down (due to multiple reasons), I had to restart it. After adding that functionality the code looks like this:

“disconnect” event is fired whenever a worker is killed. So, then I simply start a new process cluster.fork().process; .

The only thing left in this implementation is the process communication between the app workers and from app workers to the dedicated task (SMS/email/notif) workers.

Process communication:

The cluster module provides the process.message method to send a message to the master. With this, I was able to listen to different messages from the app and send it to the relevant worker. After adding process communication, the final code looks like this:

I have defined global methods so that I can send messages from anywhere in the app to the worker. When I call global.emailWorker.send(“Email to send”); method from the app, it sends a message to the master process and then the master process forwards it to relevant child_process .

You’ll notice how global.smsWorker is started.

global.smsWorker = require(‘child_process’).fork(‘./smsWorker’);

smsWorker.js, emailWorker.js & notifWorker.js files are a function listening to messages on process to do relevant task.

For a more clear understanding of the flow of communication between processes, take a look at this: