Mastering Processes and Threads in Node.js: From Basics to Multi‑Process Architecture
This comprehensive guide explains the fundamentals of processes and threads, demonstrates practical Node.js demos for single‑threaded and multi‑threaded scenarios, and walks through creating child processes, multi‑process architectures, and daemon services, providing clear code examples and performance insights for backend developers.
Quick Navigation
Process
Thread
Node.js Thread and Process
Node.js Process Creation
Node.js Multi‑process Architecture Model
Daemon Process
Process
Process is the basic unit of resource allocation in an operating system and serves as a container for threads. A simple Node.js process can be started with node app.js. The example shows how to set process.title, read process.pid, and use a demo file process.js to display the PID.
const http = require('http');
http.createServer(() => {
process.title = 'Test Process Node.js';
console.log(`process.pid: ${process.pid}`);
}).listen(3000);Thread
Thread is the smallest unit of CPU scheduling and belongs to a process. JavaScript runs in a single‑threaded event loop, while languages like Java support true multithreading. The article provides a blocking computation example that illustrates why asynchronous code is essential in Node.js.
// compute.js
const http = require('http');
http.createServer((req, res) => {
if (req.url === '/compute') {
// heavy computation
} else {
res.end('ok');
}
}).listen(3000);Single Thread
JavaScript executes code sequentially; long‑running synchronous operations block the event loop. Using asynchronous APIs prevents this blockage.
Multi Thread
Java multithreading example demonstrates a shared variable count that is modified by multiple threads, showing how each thread has its own stack but shares the process memory.
public class TestApplication {
static Integer count = 0;
// ...
}Node.js Thread and Process
Node.js runs on the V8 engine, employing an event‑driven, non‑blocking I/O model. It can operate in a single‑process single‑thread mode or a multi‑process single‑thread mode using child_process.fork (Cluster) to leverage multiple CPU cores.
Process Object
process.env – environment variables
process.nextTick – next‑tick queue
process.pid – current process ID
process.ppid – parent process ID
process.cwd() – current working directory
process.platform – OS platform
process.uptime() – process uptime
process.on('uncaughtException') – catch uncaught errors
process.stdout, process.stdin, process.stderr – standard streams
Node.js Process Creation
spawn
const { spawn } = require('child_process');
const child = spawn('ls', ['-l'], { cwd: '/usr' });
child.stdout.pipe(process.stdout);exec
const { exec } = require('child_process');
exec('node -v', (error, stdout, stderr) => {
console.log({ error, stdout, stderr });
});execFile
const { execFile } = require('child_process');
execFile('node', ['-v'], (error, stdout, stderr) => {
console.log({ error, stdout, stderr });
});fork
const { fork } = require('child_process');
const compute = fork('./fork_compute.js');
compute.send('start computation');
compute.on('message', sum => {
// handle result
});Using fork for CPU‑intensive Tasks
A parent server delegates heavy computation to a child process via process.send and receives the result with a message event.
// fork_app.js (parent)
const { fork } = require('child_process');
const compute = fork('./fork_compute.js');
compute.send('start');
compute.on('message', sum => {
res.end(`Sum is ${sum}`);
compute.kill();
});Node.js Multi‑process Architecture Model
The master process creates a TCP server, forks worker processes equal to the number of CPU cores, distributes incoming connections, restarts workers on exit, and handles graceful shutdown signals.
// master.js
const { fork } = require('child_process');
const cpus = require('os').cpus().length;
const server = require('net').createServer();
server.listen(3000);
function createWorker() {
const worker = fork('worker.js');
worker.on('message', msg => {
if (msg.act === 'suicide') createWorker();
});
worker.on('exit', (code, signal) => {
delete workers[worker.pid];
// optional restart logic
});
worker.send('server', server);
workers[worker.pid] = worker;
}
for (let i = 0; i < cpus; i++) createWorker();
process.once('SIGINT', close.bind(this,'SIGINT'));Worker code creates its own HTTP server, receives the shared server handle from the master, and demonstrates error handling with process.on('uncaughtException').
// worker.js
process.title = 'node-worker';
process.on('message', (msg, handle) => {
if (msg === 'server') {
const server = handle;
server.on('connection', socket => {
// handle connection
});
}
});
process.on('uncaughtException', err => {
process.send({ act: 'suicide' });
process.exit(1);
});Daemon Process
A daemon runs in the background after its parent exits. The example creates a detached child process with detached: true, sets its working directory, ignores stdio, and calls unref() so the parent can terminate.
// index.js
const { spawn } = require('child_process');
function startDaemon() {
const daemon = spawn('node', ['daemon.js'], {
cwd: '/usr',
detached: true,
stdio: 'ignore'
});
console.log(`Daemon started parent pid: ${process.pid}, daemon pid: ${daemon.pid}`);
daemon.unref();
}
startDaemon();The daemon script logs its PID and PPID every 10 seconds to log files, keeping the process alive.
// daemon.js
const fs = require('fs');
const { Console } = require('console');
const logger = new Console(
fs.createWriteStream('./stdout.log'),
fs.createWriteStream('./stderr.log')
);
setInterval(() => {
logger.log('daemon pid:', process.pid, 'ppid:', process.ppid);
}, 10000);Running node index.js starts the daemon, which can be observed in the system activity monitor as a separate background process.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Node Underground
No language is immortal—Node.js isn’t either—but thoughtful reflection is priceless. This underground community for Node.js enthusiasts was started by Taobao’s Front‑End Team (FED) to share our original insights and viewpoints from working with Node.js. Follow us. BTW, we’re hiring.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
