Node.js Clustering for Multi-Core CPUs
Understand Node.js clustering. Use all CPU cores to handle more traffic.
Node.js Clustering
The Problem: Single-Threaded Limitation
Node.js runs on a single thread. This means: - Your app uses only 1 CPU core - On a 4-core CPU, you're using 25% of available power - Other 3 cores sit idle doing nothing - One heavy request blocks others
``` 4-Core CPU: Core 1: ████████ (Node.js running here) Core 2: -------- (idle) Core 3: -------- (idle) Core 4: -------- (idle)
Result: 75% of CPU wasted! ```
What is Clustering?
Clustering creates multiple Node.js processes (workers) that: - Share the same server port - Each runs on a different CPU core - Work independently - Handle requests in parallel
``` Master Process (manages workers) ├── Worker 1 (Core 1) → Handles Request A ├── Worker 2 (Core 2) → Handles Request B ├── Worker 3 (Core 3) → Handles Request C └── Worker 4 (Core 4) → Handles Request D
All 4 requests processed simultaneously! ```
How Clustering Works
```javascript const cluster = require('cluster'); const os = require('os'); const express = require('express');
if (cluster.isMaster) { const numCPUs = os.cpus().length; console.log(`Master process running. CPU cores: ${numCPUs}`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker) => { console.log(`Worker ${worker.process.pid} died`); cluster.fork(); }); } else { const app = express(); app.get('/', (req, res) => { res.send(`Handled by worker ${process.pid}`); }); app.listen(3000); console.log(`Worker ${process.pid} started`); } ```
**Explanation:** 1. **Master process** checks `cluster.isMaster` 2. Master creates workers with `cluster.fork()` 3. **Worker processes** run your Express app 4. OS automatically distributes requests 5. If worker crashes, master restarts it
Benefits of Clustering
**1. Better Performance** ``` Without Clustering: 100 req/sec With Clustering (4 cores): 380 req/sec ```
**2. Fault Tolerance** If one worker crashes, others keep running.
**3. Zero Downtime Restarts** Restart workers one by one.
**4. Full CPU Utilization** Use all cores instead of just one.
Using PM2 (Production Ready)
PM2 is a process manager that handles clustering automatically.
```bash npm install -g pm2
pm2 start app.js -i max
pm2 list pm2 logs pm2 monit ```
**`-i max`** = Use all CPU cores
No code changes needed! PM2 handles everything.
Critical Issue: Shared State
```javascript let counter = 0;
app.get('/', (req, res) => { counter++; res.send(`Count: ${counter}`); }); ```
**Problem:** Each worker has its own `counter` variable!
``` Worker 1: counter = 5 Worker 2: counter = 3 Worker 3: counter = 7 Worker 4: counter = 2
Total should be 17, but each worker shows different count! ```
**Solution: Use Redis for shared state**
```javascript const redis = require('redis'); const client = redis.createClient();
app.get('/', async (req, res) => { const count = await client.incr('counter'); res.send(`Count: ${count}`); }); ```
Now all workers share the same counter in Redis.
When to Use Clustering
**✅ Use When:** - CPU-intensive operations - High traffic applications - Need fault tolerance - Multiple CPU cores available
**❌ Don't Use When:** - I/O-bound operations (database queries) - Single-core server - Shared memory needed (use Worker Threads instead)
Key Takeaway
Clustering multiplies your app's capacity by using all CPU cores. Use PM2 in production for automatic management. Workers don't share memory - use Redis for shared state. Each worker is independent, so if one crashes, others keep serving requests.