Bird
Raised Fist0
Node.jsframework~3 mins

Why Forking workers per CPU core in Node.js? - Purpose & Use Cases

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
The Big Idea

What if your server could magically use every CPU core to handle more users without extra hassle?

The Scenario

Imagine you have a Node.js server that handles many user requests at once, but it runs on a single CPU core.

When many users connect, the server slows down and some requests wait a long time.

The Problem

Using just one core means your server can only do one thing at a time.

This causes delays and poor performance when traffic is high.

Trying to manage multiple tasks manually is complex and error-prone.

The Solution

Forking workers per CPU core lets Node.js create multiple processes, one for each core.

Each worker handles requests independently, making full use of all CPU cores.

This improves speed and reliability without complicated manual management.

Before vs After
Before
const http = require('http');
http.createServer((req, res) => {
  res.end('Hello World');
}).listen(8000);
After
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  http.createServer((req, res) => {
    res.end('Hello from worker');
  }).listen(8000);
}
What It Enables

This approach enables your server to handle many requests quickly by using all CPU cores efficiently.

Real Life Example

A busy online store uses forking workers to serve thousands of shoppers at once without slowing down during sales.

Key Takeaways

Single-core servers struggle with many requests.

Forking creates multiple workers, one per CPU core.

This improves performance and reliability easily.

Practice

(1/5)
1. What is the main reason to fork workers equal to the number of CPU cores in a Node.js app?
easy
A. To make the app run slower for debugging purposes
B. To use all CPU cores and improve performance by running tasks in parallel
C. To reduce memory usage by limiting the number of processes
D. To avoid using the cluster module

Solution

  1. Step 1: Understand CPU cores and parallelism

    Each CPU core can run one process at a time, so using all cores means better performance.
  2. Step 2: Role of forking workers

    Forking workers equal to CPU cores lets Node.js run multiple tasks simultaneously, improving speed.
  3. Final Answer:

    To use all CPU cores and improve performance by running tasks in parallel -> Option B
  4. Quick Check:

    Fork workers = use all cores = better performance [OK]
Hint: More workers = more CPU cores used = faster app [OK]
Common Mistakes:
  • Thinking forking reduces memory usage
  • Believing forking slows the app
  • Confusing cluster module usage
2. Which of the following is the correct way to get the number of CPU cores in Node.js for forking workers?
easy
A. const cores = require('os').cpus().length;
B. const cores = require('cluster').cpuCount;
C. const cores = require('os').cpuCount();
D. const cores = require('os').cpus.length;

Solution

  1. Step 1: Check Node.js os module usage

    The os module has a method cpus() that returns an array of CPU core info.
  2. Step 2: Correct syntax to get core count

    Using cpus().length gives the number of CPU cores available.
  3. Final Answer:

    const cores = require('os').cpus().length; -> Option A
  4. Quick Check:

    os.cpus() returns array, length gives core count [OK]
Hint: Use os.cpus().length to count CPU cores [OK]
Common Mistakes:
  • Forgetting parentheses after cpus
  • Using non-existent cpuCount method
  • Trying to get cores from cluster module
3. Given this code snippet, what will be logged when run on a machine with 4 CPU cores?
const cluster = require('cluster');
const os = require('os');

if (cluster.isPrimary) {
  const numCPUs = os.cpus().length;
  console.log(`Primary process is running`);
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  console.log(`Worker ${process.pid} started`);
}
medium
A. Primary process is running Worker 1234 started Worker 1235 started Worker 1236 started Worker 1237 started
B. Primary process is running Worker started Worker started Worker started Worker started
C. Primary process is running Worker 1234 started
D. SyntaxError due to missing cluster setup

Solution

  1. Step 1: Identify primary and worker behavior

    The primary logs once and forks 4 workers (one per CPU core).
  2. Step 2: Each worker logs its own process id

    Each worker logs "Worker [pid] started" with its unique process id.
  3. Final Answer:

    Primary process is running Worker 1234 started Worker 1235 started Worker 1236 started Worker 1237 started -> Option A
  4. Quick Check:

    Primary logs once, 4 workers log with pids [OK]
Hint: Primary logs once; each worker logs with unique pid [OK]
Common Mistakes:
  • Assuming workers log without pid
  • Thinking only one worker starts
  • Confusing primary and worker logs
4. What is wrong with this code snippet that tries to fork workers per CPU core?
const cluster = require('cluster');
const os = require('os');

if (cluster.isPrimary) {
  const numCPUs = os.cpus.length;
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  console.log('Worker started');
}
medium
A. cluster.fork() is not a function
B. No error; code works fine
C. Missing else block for worker process
D. os.cpus.length is undefined; should be os.cpus().length

Solution

  1. Step 1: Check os module usage

    os.cpus is a function, so os.cpus.length is undefined and causes error.
  2. Step 2: Correct usage

    Use os.cpus().length to get the number of CPU cores correctly.
  3. Final Answer:

    os.cpus.length is undefined; should be os.cpus().length -> Option D
  4. Quick Check:

    os.cpus() is function, need parentheses [OK]
Hint: Remember os.cpus() is a function, not a property [OK]
Common Mistakes:
  • Forgetting parentheses on os.cpus()
  • Assuming cluster.fork() is missing
  • Thinking else block is required for syntax
5. You want to create a Node.js server that forks one worker per CPU core and restarts any worker if it crashes. Which code snippet correctly implements this behavior?
hard
A. const cluster = require('cluster'); const http = require('http'); const os = require('os'); if (cluster.isPrimary) { const numCPUs = os.cpus().length; for (let i = 0; i < numCPUs; i++) { cluster.fork(); } } else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello from worker ' + process.pid); }).listen(8000); cluster.on('exit', (worker) => { console.log(`Worker ${worker.process.pid} died`); }); }
B. const cluster = require('cluster'); const http = require('http'); const os = require('os'); if (cluster.isWorker) { const numCPUs = os.cpus().length; for (let i = 0; i < numCPUs; i++) { cluster.fork(); } } else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello from worker ' + process.pid); }).listen(8000); }
C. const cluster = require('cluster'); const http = require('http'); const os = require('os'); if (cluster.isPrimary) { const numCPUs = os.cpus().length; for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker) => { console.log(`Worker ${worker.process.pid} died, restarting...`); cluster.fork(); }); } else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello from worker ' + process.pid); }).listen(8000); }
D. const cluster = require('cluster'); const http = require('http'); const os = require('os'); if (cluster.isPrimary) { cluster.fork(); } else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello from worker ' + process.pid); }).listen(8000); }

Solution

  1. Step 1: Fork one worker per CPU core in primary process

    In if (cluster.isPrimary), use const numCPUs = os.cpus().length; for (let i = 0; i < numCPUs; i++) cluster.fork();
  2. Step 2: Restart workers on exit event

    In primary process, cluster.on('exit', (worker) => { console.log(`Worker ${worker.process.pid} died, restarting...`); cluster.fork(); });
  3. Step 3: Worker creates HTTP server

    Workers create the HTTP server listening on port 8000, responding with their pid.
  4. Final Answer:

    forks one worker per CPU core and restarts any worker if it crashes -> Option C
  5. Quick Check:

    Primary forks os.cpus().length + cluster.on('exit', fork()) + workers create HTTP server [OK]
Hint: Use cluster.on('exit') in primary to restart workers [OK]
Common Mistakes:
  • Using cluster.isWorker instead of cluster.isPrimary
  • Not restarting workers on exit
  • Forking workers inside worker process