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: ${total}`);
});
app.listen(port, () => {
console.log(`Uygulama ${port} 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 { dirname } from "path";
import { fileURLToPath } 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:
-
Single process: low request/second
-
Cluster active: 3–4 times higher throughput
-
Average latency drops dramatically
7. Auto Scaling with PM2 (Recommended)
pm2 start index.js -i 0
- This command creates as many processes as the number of CPUs.
Advantages:
-
Automatic restart
-
Log management
-
Uninterrupted restart (zero-downtime)
8. PM2 Management Commands
| Command | Description |
|---|---|
pm2 list | Shows running processes |
pm2 restart app | Restarts the application |
pm2 reload app | Reloads without interruption |
pm2 stop app | Stops the application |
pm2 delete app | Deletes 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.

