×

How does Node.js Backend Handle 700% More Traffic Using Cluster and Multithreading

image of Ranxin Li
Ranxin Li

August 8

As the demand for modern technologies continues to grow, multithreading is becoming increasingly common and essential. It allows a program to execute multiple threads concurrently within the same process.
image of How does Node.js Backend Handle 700% More Traffic Using Cluster and Multithreading

Node JS Multi Threading helps handle traffic

Many programming languages support multithreading out of the box, including C++, Java, C#, Go, Rust, and more. However, some languages present challenges: Python is limited by the Global Interpreter Lock (GIL), and JavaScript, traditionally single-threaded, lacks native threading capabilities.

To solve this problem, we turn to a powerful solution: Worker Threads. They allow us to offload CPU-intensive tasks into separate threads without blocking the main event loop.

In this article, I will discuss about how I used Worker Threads to implement multithreading in a Node.js backend — and how this approach helped us scale our system to handle significantly more traffic.

Node.js is single-threaded by default, which means that even on an 8-core CPU, it will only utilize one core. This becomes a main limitation in scenarios such as real-time messaging via WebSocket, background checks and user matching, AI-powered fake profile detection, or simply when handling a high volume of users’ requests. In these cases, parallelizing the workload is not just beneficial — it’s essential for maintaining performance and responsiveness.

During my internship in 2024, I was responsible for full-stack mobile development, using React Native for the frontend and Node.js for the backend. While working on the user matching feature, I noticed that the backend performance was suffering due to Node.js utilizing only a single CPU core. To address this issue, I implemented multithreading using Node.js’s cluster and worker_threads modules.

We focus on two main steps:

  1. Implementing Node.js Cluster: The cluster module lets you fork multiple Node.js processes that share the same server port. Here is the code implementation
import cluster from 'cluster';
import os from 'os';
import app from './app';
if (cluster.isPrimary) {
const numCPUs = os.cpus().length;
console.log(`Primary ${process.pid} is running`);
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker) => {
console.log(`Worker ${worker.process.pid} died. Restarting...`);
cluster.fork();
});
} else {
app.listen(3000, () => {
console.log(`Worker ${process.pid} started`);
});
}

2. Offloading Heavy Tasks with Worker Threads

import { Worker } from 'worker_threads';
function runHeavyTask(data) {
return new Promise((resolve, reject) => {
const worker = new Worker('./heavy-task.js', { workerData: data });
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
}

Here are the performance results after testing:
 Before implementing multicore processing, the server could handle only around 200 requests per second. After deploying the cluster and worker_threads solution, throughput increased to over 1,600 requests per second. The average user response time dropped by approximately 62%, and user complaints dropped to nearly zero.

If you want to go further, you can do the following things:

  • Use PM2 for cluster management and monitoring.
  • Use message queues (like Redis or BullMQ) for distributed task handling.

Let me explain how those suggestion works:

PM2 is a process manager for Node.js applications, which helps you manage and monitor your app in production. It will restart the application when the system crushes and make it easy to run your application in cluster mode.

A message queue allows services or parts of your system to communicate asynchronously by sending and receiving tasks or messages through a queue. We use it when we offload heavy or delayed tasks (e.g., image processing, emails), balance workload across multiple threads or even machines, and Prevents blocking the main thread in real-time systems.

All in all, Node.js is not slow and what you need to do is just to use all of your CPU. We use cluster to help with I/O concurrency and worker threads for offloading CPU-heavy logic. Make sure always monitoring for memory leaks when using multiple workers.

Node JS AI Multi Threading