Backend Development 11 min read

Mastering Node.js Multi‑Process: From spawn to cluster for High Concurrency

This article explains process and thread fundamentals, describes Node.js's single‑threaded nature, and provides detailed guidance on using the child_process module (spawn, fork, exec, execFile) and the cluster module to create, manage, and communicate between multiple Node.js processes for scalable, high‑concurrency applications.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Mastering Node.js Multi‑Process: From spawn to cluster for High Concurrency

1. Review of Process and Thread Definitions

Process is the basic unit of resource allocation and scheduling in an operating system, representing a program’s execution on a set of data. Thread is the smallest unit of execution that the OS can schedule, existing within a process as the actual work unit.

2. Node.js Single Thread

Node.js runs a single main thread; it is event‑driven, asynchronous, and non‑blocking, making it suitable for high‑concurrency scenarios. Because Node lacks built‑in multithreading, developers use child processes to leverage multiple CPU cores.

Blocking issues when performing time‑consuming calculations.

How to start multiple processes in Node.js.

How to keep a process alive (daemon).

3. Example Scenario

<code>const http = require('http');
http.createServer((req, res) => {
  if (req.url === '/sum') {
    let sum = 0;
    for (let i = 0; i < 10000000000; i++) {
      sum += i;
    }
    res.end(sum + '');
  } else {
    res.end('end');
  }
}).listen(3000);
// Access /sum first, then a new browser tab for / – the second request waits until /sum finishes.</code>

4. Creating Processes

Node.js creates processes through the

child_process

module:

child_process.spawn()

– asynchronous creation of a child process.

child_process.fork()

– creates a new Node.js process with an IPC channel for message passing.

child_process.exec()

– runs a command in a shell.

child_process.execFile()

– runs a file directly without a shell.

4.1 spawn

Spawn creates a child process and can share standard I/O streams.

<code>let { spawn } = require('child_process');
let path = require('path');
let childProcess = spawn('node', ['sub_process.js'], {
  cwd: path.resolve(__dirname, 'test'),
  stdio: [0, 1, 2]
});
childProcess.on('error', function (err) { console.log(err); });
childProcess.on('close', function () { console.log('close'); });
childProcess.on('exit', function () { console.log('exit'); });
</code>

The

stdio

option can be set to

['pipe']

(default) to communicate via streams, or to

['pipe','pipe','pipe','ipc']

to add an IPC channel.

4.2 fork

Fork is built on spawn and automatically creates an IPC channel.

<code>let { fork } = require('child_process');
let path = require('path');
let childProcess = fork('sub_process.js', {
  cwd: path.resolve(__dirname, 'test')
});
childProcess.on('message', function (data) { console.log(data); });
</code>

Fork can accept a

silent

option; when true, stdio is set to

['ignore','ignore','ignore']

before adding the IPC channel.

4.3 execFile

ExecFile runs a file directly using Node.

<code>let childProcess = execFile('node', ['./test/sub_process'], function (err, stdout, stderr) {
  console.log(stdout);
});
</code>

4.4 exec

Exec runs a command in a shell; internally it uses execFile, which in turn uses spawn.

<code>let childProcess = exec("node './test/sub_process'", function (err, stdout, stderr) {
  console.log(stdout);
});
</code>

5. Cluster

Node.js runs a single instance in one thread. To utilize multi‑core systems, you can manually create a process cluster or use the built‑in

cluster

module.

Sharing an HTTP server between parent and child using fork and IPC:

<code>// Parent process
let http = require('http');
let { fork } = require('child_process');
let path = require('path');
let child = fork(path.join(__dirname, '8.child.js'));
let server = net.createServer();
server.listen(8080, '127.0.0.1', function () {
  child.send('server', server);
  console.log('Parent server created');
  let httpServer = http.createServer();
  httpServer.on('request', function (req, res) {
    if (req.url !== '/favicon.ico') {
      let sum = 0;
      for (let i = 0; i < 100000; i++) sum += 1;
      res.write('Request handled in parent.');
      res.end('sum=' + sum);
    }
  });
  httpServer.listen(server);
});

// Child process (8.child.js)
process.on('message', function (msg, server) {
  if (msg === 'server') {
    console.log('Child server created');
    let httpServer = http.createServer();
    httpServer.on('request', function (req, res) {
      if (req.url !== '/favicon.ico') {
        let sum = 0;
        for (let i = 0; i < 10000; i++) sum += i;
        res.write('Request handled in child.');
        res.end('sum=' + sum);
      }
    });
    httpServer.listen(server);
  }
});
</code>

Sharing a socket object between processes:

<code>// Parent process
let child = fork(path.join(__dirname, '11.socket.js'));
let server = require('net').createServer();
server.on('connection', function (socket) {
  if (Date.now() % 2 === 0) {
    child.send('socket', socket);
  } else {
    socket.end('Handled by parent');
  }
});
server.listen(41234);

// Child process (11.socket.js)
process.on('message', function (msg, socket) {
  if (msg === 'socket') {
    socket.end('Handled by child');
  }
});
</code>

Using the cluster module for automatic worker management:

<code>let cluster = require('cluster');
let http = require('http');
let cpus = require('os').cpus().length;
let workers = {};
if (cluster.isMaster) {
  cluster.on('exit', function (worker) {
    console.log(worker.process.pid, 'death');
    let w = cluster.fork();
    workers[w.pid] = w;
  });
  for (let i = 0; i < cpus; i++) {
    let worker = cluster.fork();
    workers[worker.pid] = worker;
  }
} else {
  http.createServer((req, res) => {
    res.end(process.pid + '');
  }).listen(3000);
  console.log('server start', process.pid);
}
</code>
backendNode.jsClusterchild_processForkexecspawn
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.