Support Online
Skip to main content

Node.js Performance Boost: Application Scaling with Clustering and PM2

What will you learn in this guide?

In this guide, you'll learn how to scale Node.js applications on multi-core systems.
You will do manual scaling with the Cluster module, then automate the process with PM2.
Finally, you will clearly measure the performance difference with load tests.

🧠 Technical Summary

The topic is to increase CPU usage in Node.js applications.
The problem is that Node.js uses a single core by default.
The solution is to run multiple processes with cluster and PM2.


Preliminary Preparations

Before continuing, the following is required:

  • 4 or more CPU cores (physical or GenixNode VDS)
  • Node.js and npm installed environment
  • Basic knowledge of Express.js
  • Familiarity with terminal usage

1. Why Does Node.js Need Scaling?

Node.js runs JavaScript codes in a single thread.
All requests run through a single process.
CPU-intensive operations severely reduce performance.

Results:

  • High latencies
  • Risk of process crash
  • Unused CPU cores

2. What is Cluster Module?

Cluster spawns multiple processes from the same application.
Each process runs on a different CPU core.
Requests are distributed using the round-robin algorithm.

Advantages:

  • More concurrent requests
  • Lower response time
  • Service continues even if the process crashes

3. Project Setup

mkdir genixnode-cluster-demo
cd genixnode-cluster-demo
npm init -y
npm install express
npm install -g loadtest pm2
  • These steps prepare the project structure and necessary tools.

4. Implementing a Single Process Without Clustering


import express from "express";

const app = express();
const port = 3000;

console.log(`Worker PID: ${process.pid}`);

app.get("/heavy", (req, res) => {
let total = 0;
for (let i = 0; i < 5_000_000; i++) {
total++;
}
res.send(`Hesaplama sonucu: $&#123;total&#125;`);
});

app.listen(port, () => {
console.log(`Uygulama $&#123;port&#125; portunda çalışıyor`);
});
  • This code simulates a CPU intensive workload.

5. Using Multi-Core with Cluster


import cluster from "cluster";
import os from "os";
import &#123; dirname &#125; from "path";
import &#123; fileURLToPath &#125; from "url";

const __dirname = dirname(fileURLToPath(import.meta.url));
const cpuCount = os.cpus().length;

cluster.setupPrimary({
exec: __dirname + "/index.js",
});

for (let i = 0; i < cpuCount; i++) {
cluster.fork();
}

cluster.on("exit", () => {
cluster.fork();
});
  • This code starts as many workers as the number of CPUs.

6. Performance Comparison (Load Test)


loadtest -n 1200 -c 200 -k http://localhost:3000/heavy
  • This command generates concurrent traffic.

Expected results:

  1. Single process: low request/second

  2. Cluster active: 3–4 times higher throughput

  3. Average latency drops dramatically



pm2 start index.js -i 0
  • This command creates as many processes as the number of CPUs.

Advantages:

  1. Automatic restart

  2. Log management

  3. Uninterrupted restart (zero-downtime)


8. PM2 Management Commands

CommandDescription
pm2 listShows running processes
pm2 restart appRestarts the application
pm2 reload appReloads without interruption
pm2 stop appStops the application
pm2 delete appDeletes the application

❓ Frequently Asked Questions

1. How are database connections affected? Each worker opens a separate connection. Connection pool settings should be made accordingly.

2. Do workers share RAM? No. Each process is isolated. Sharing requires solutions like Redis.

3. What happens when a worker crashes? Cluster and PM2 automatically start a new one.

""4. Does this build work on GenixNode VDS?"" Yes. Ideal on multi-core GenixNode servers.


Result

In this guide, you made your Node.js application scalable. You have made full use of hardware resources with Cluster and PM2. You clearly saw the performance difference with the load tests.

You can safely publish your scalable Node.js projects on the GenixNode infrastructure.