Node.js runs JavaScript on a single main thread. The cluster module forks worker processes that share server ports so HTTP servers can use every CPU core.
Each worker is a full process with its own V8 heap and event loop. Isolation prevents heap corruption across workers but also means in-memory Maps are not shared.
This guide covers primary/worker lifecycle, scheduling, IPC, rolling restarts, sticky sessions, PM2, and when to prefer containers.
ℹ
info
Hand-rolled cluster teaches the model; production often uses PM2 or Kubernetes replicas.
Primary vs Worker
Use cluster.isPrimary. The primary forks workers; workers call listen() on the same port.
Calling process.exit in the primary kills the tree
✕
danger
Primary process.exit terminates all workers.
Mental Model
Treat cluster as a contract with the OS and the Node.js event loop. Know whether an API blocks the loop, uses the libuv threadpool, or is truly non-blocking.
Debug questions: Am I holding the event loop? Leaking handles? Sharing state across processes? Handling partial failure? Timing out outbound I/O?
Question
Healthy
Smell
CPU burn
Worker / child / addon
Sync loops on request path
I/O wait
Async fs/net/http
Sync fs in handlers
Crash survival
External store
RAM-only state
Shutdown
Drain + close
Hard exit mid-request
API Habits
Prefer promise APIs for cluster. Use node: import prefixes. Avoid mixing callback and async styles in one function.
Servers, sockets, watchers, and timers keep the process alive. Close them on shutdown. Always set timeouts on outbound work.
timeouts.mjs
JavaScript
1
export async function withTimeout(promise, ms, label = "op") {
2
let to;
3
const timeout = new Promise((_, rej) => {
4
to = setTimeout(() => {
5
const e = new Error(`${label} timed out after ${ms}ms`);
6
e.code = "ETIMEDOUT";
7
rej(e);
8
}, ms);
9
});
10
try {
11
return await Promise.race([promise, timeout]);
12
} finally {
13
clearTimeout(to);
14
}
15
}
⚠
warning
Uncleared intervals prevent clean exit in tests involving cluster.
Concurrency Limits
Node can open thousands of async operations. Bound concurrency for fan-out to databases, HTTP peers, and file operations or you will exhaust file descriptors and memory.
limit.mjs
JavaScript
1
export function pLimit(concurrency) {
2
let active = 0;
3
const queue = [];
4
const next = () => {
5
if (active >= concurrency || queue.length === 0) return;
Anything touching paths, URLs, child processes, crypto, or network input needs validation. Never interpolate untrusted strings into shells or file paths near cluster.
Validate and normalize paths with path.resolve + root jail
Prefer spawn with argument arrays over shell exec
Use timingSafeEqual for secret compares
Set restrictive CORS and security headers on HTTP APIs
✕
danger
Never log raw Authorization headers, cookies, or private keys.
Performance Notes
Measure before optimizing cluster. Use node --cpu-prof, clinic.js, or OpenTelemetry. Watch event-loop delay metrics.
el-delay.mjs
JavaScript
1
import { monitorEventLoopDelay } from "node:perf_hooks";
2
3
const h = monitorEventLoopDelay({ resolution: 20 });
4
h.enable();
5
setInterval(() => {
6
console.log({
7
meanMs: (h.mean / 1e6).toFixed(2),
8
p99Ms: (h.percentile(99) / 1e6).toFixed(2),
9
});
10
h.reset();
11
}, 5000).unref();
FAQ
When do I use this topic?
Reach for cluster when its responsibility matches the problem. Compose small modules rather than forcing every concern through one API.
Cross-platform?
Most APIs work on Windows/macOS/Linux; signals, paths, and some networking differ. Test where you deploy.
Agent verification
Generate a runnable example, run tests, fail closed if timeouts/errors/shutdown are missing.
In reviews, search for empty catch blocks and missing await — both are high-signal smells.
Interop & Version Notes
APIs around cluster evolve across Node majors. Read changelogs when upgrading. Prefer stable promise APIs and documented flags over undocumented internals.
Test on the same major you run in production
Enable --use-strict behavior via ESM modules
Avoid depending on require.extensions hacks
Document any experimental flags in README and CI
version-matrix.sh
Bash
1
node -p process.versions
2
npm ls --depth=0
3
# CI matrix: 20.x LTS, 22.x LTS
Agent Generation Checklist
Before claiming mastery of cluster, generated artifacts must pass this checklist.
Uses node: import prefixes where applicable
Errors have codes and are not swallowed
Outbound I/O has timeouts / AbortSignal
Resources closed in finally / shutdown
No shell interpolation of user input
Tests cover at least one failure path
Logs are structured; secrets redacted
✕
danger
Do not advance curriculum stages after reading titles only — fetch full markdown and verify with runnable code.