Modern Node.js applications must handle hundreds of thousands of requests with minimal latency. The two most popular scaling mechanisms are the built‑in cluster and the PM2 process manager. In this article we break down how they work, measure their performance impact, and explain when to choose one solution over the other.
How Does Node.js Cluster Work?
The cluster module is part of Node.js’s standard library. It creates a group of worker processes that share the same TCP port via a master‑worker mechanism. The master accepts connections and distributes them either round‑robin or using the os.sched algorithm depending on the platform.
Sample implementation:
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} startuje`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} zmarł, restartuję`);
cluster.fork();
});
} else {
http.createServer((req, res) => {
res.writeHead(200);
res.end('Hello from worker ' + process.pid);
}).listen(3000);
}
Key characteristics:
- No external dependencies – works since Node 0.8.
- Automatic restart of a single process after a crash.
- Memory sharing is not possible – each worker has its own heap.
What Does PM2 Offer?
PM2 is a process manager written in Node.js, available as an npm package. Beyond simply launching multiple instances, PM2 provides:
- Load balancing using the built‑in
cluster_modemodule (based on the same API ascluster). - Zero‑downtime reloads (the
pm2 reloadcommand). - Real‑time monitoring (PM2‑Monit, Keymetrics).
- Built‑in watchdog, log rotation, and systemd support.
Basic configuration in ecosystem.config.js:
module.exports = {
apps: [{
name: 'api',
script: './src/server.js',
instances: 'max', // uses all cores
exec_mode: 'cluster',
watch: false,
env: { NODE_ENV: 'production' }
}]
};
After running pm2 start ecosystem.config.js the manager handles restarts, scaling, and reporting.
Cluster vs PM2 Performance in Production
In terms of raw throughput the differences are minimal, because PM2 in cluster mode uses exactly the same Node.js mechanism. The main factors affecting results are:
- Master communication overhead – PM2 adds an IPC layer for monitoring, which in the worst case increases CPU usage by ~2‑3% under high QPS.
- Restart strategy – PM2 can perform a graceful reload without dropping connections, which is crucial for continuous availability.
- Memory management – PM2 allows automatic memory limiting (
max_memory_restart), reducing the risk of memory leaks in long‑running processes.
In practical tests (e.g., 100 000 GET /api requests in 30 s) the average response time difference was 1‑2 ms in favor of plain cluster, but PM2 delivered more stable results when workers failed randomly.
When to Use Cluster and When to Use PM2?
Node.js Cluster is a good choice when:
- You need a minimal dependency stack and want to control every detail of the master code.
- The application is simple and processes don’t require advanced monitoring.
- The runtime environment doesn’t allow installing extra packages (e.g., ultra‑small containers).
PM2 shines when:
- You require zero‑downtime deployments and automatic restarts after memory limits are hit.
- You want centralized resource monitoring and a dashboard.
- The project is distributed and needs integration with an init system (systemd, upstart).
Practical Implementation Checklist
- Check the number of available CPUs (
os.cpus().length) and set the worker count to that value or'max'in PM2. - Define a memory limit (
max_memory_restartin PM2 or a custom watchdog in Cluster) – typically 300 MiB for API processes. - Configure logging – PM2 handles rotation; with Cluster you must manually redirect
stdout/stderr. - Test a failure scenario: kill one worker and verify that the master/PM2 automatically respawns it.
- Zero‑downtime deployment: use
pm2 reloadwith PM2, or implementcluster.disconnect()andcluster.fork()manually in plain Cluster.
Typical pitfalls and trade‑offs
1. Using one process per CPU – in some cases two workers per core are better when the application is I/O‑bound and does not fully utilize the CPU. However, this increases memory overhead.
2. No memory limit – both Cluster and PM2 do not restart a process by default when memory leaks occur. In PM2 you can set max_memory_restart, while in Cluster you need to monitor process.memoryUsage() and fork manually.
3. Logging in cluster mode – without centralized log collection (e.g., Winston + Elastic transport) it is difficult to analyze issues in a production environment.
“Choosing between Cluster and PM2 is not a matter of ‘better vs worse’, but of matching the tool to operational and team requirements.”
Summary and next steps
Node.js Cluster and PM2 provide a similar scaling foundation, but differ in operational features. If you need full control and minimal overhead, choose plain cluster. When automation, monitoring, and seamless deployment matter, PM2 is the natural choice. In both cases, conscious management of worker count, memory limits, and restart strategy is essential.
Have questions about scaling implementation in your infrastructure? Contact Coderia.it – we’ll help you select the optimal solution and carry out a safe implementation.



