Backend Development 14 min read

Master Node.js Child Processes: exec, spawn, fork & IPC Explained

This guide explains the Node.js child_process module, covering its purpose, the four creation methods (exec, execFile, spawn, fork), how to handle output streams, inter‑process communication, best‑practice management tips, and when to choose child processes over worker threads.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Master Node.js Child Processes: exec, spawn, fork & IPC Explained

What is the Child Process Module

The child_process core module lets you create and control subprocesses that can run system commands, scripts in other languages, or even new Node.js instances, enabling parallel execution without blocking the main event loop.

How to Use Child Processes

Child processes are useful for:

Parallel processing : Distribute work across CPU cores for CPU‑intensive tasks such as image processing or data analysis.

Running shell scripts : Use exec or spawn to execute shell commands and capture their output.

Communicating with other services : Call external APIs, run database queries, or interact with micro‑services from a child process.

Creating Child Processes

Node.js provides four main methods to create a child process: exec() , execFile() , spawn() , and fork() .

exec() Method

exec() runs a command in a shell and buffers the output, suitable for simple commands but limited by memory.

<code>const { exec } = require("child_process");
exec("df -h", (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error.message}`);
    return;
  }
  if (stderr) {
    console.error(`stderr: ${stderr}`);
    return;
  }
  const lines = stdout.trim().split("\n");
  const diskInfo = lines[1].split(/\s+/);
  const totalSpace = diskInfo[1];
  const usedSpace = diskInfo[2];
  const availableSpace = diskInfo[3];
  const usagePercent = diskInfo[4];
  console.log(`Total Space: ${totalSpace}`);
  console.log(`Used Space: ${usedSpace}`);
  console.log(`Available Space: ${availableSpace}`);
  console.log(`Usage: ${usagePercent}`);
});</code>

execFile() Method

execFile() runs an executable directly without a shell, making it more efficient than exec() .

<code>const { execFile } = require('child_process');
execFile("node", ["--version"], (error, stdout, stderr) => {
  if (error) {
    console.error(`execFile error: ${error.message}`);
    return;
  }
  if (stderr) {
    console.error(`stderr: ${stderr}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
});</code>

spawn() Method

spawn() launches a new process with stream‑based I/O, giving fine‑grained control over stdout, stderr, and exit events.

<code>const { spawn } = require("child_process");
const ls = spawn("ls", ["-lh", "/usr"]);
ls.stdout.on("data", (data) => {
  console.log(`stdout: ${data}`);
});
ls.stderr.on("data", (data) => {
  console.error(`stderr: ${data}`);
});
ls.on("close", (code) => {
  console.log(`child process exited with code ${code}`);
});</code>

fork() Method

fork() is a specialized version of spawn() for creating new Node.js processes and sets up an IPC channel for message passing.

<code>// parent.js
const { fork } = require("child_process");
const child = fork("child.js");
child.on("message", (msg) => {
  console.log("Message from child:", msg);
});
child.send("Hello, child process!");

// child.js
process.on("message", (msg) => {
  console.log("Message from parent:", msg);
  process.send("Hello from child!");
});</code>

Handling Child Process Output

Child processes emit stdout and stderr streams. Listen to the data event on each stream, handle error events, and use the close event to detect when the process finishes.

<code>const { spawn } = require("child_process");
const child = spawn("echo", ["Hello, world"]);
child.stdout.on("data", (data) => {
  console.log(`stdout: ${data}`);
});
child.stderr.on("data", (data) => {
  console.error(`stderr: ${data}`);
});
child.on("error", (error) => {
  console.error(`Error occurred: ${error.message}`);
});
child.on("close", (code) => {
  console.log(`Child process exited with code ${code}`);
});</code>

Inter‑Process Communication (IPC)

Node.js enables IPC between a parent and its child processes using the send() method and the message event.

<code>// parent.js
const { fork } = require("child_process");
const child = fork("./child.js");
child.send({ greeting: "Hello from parent!" });
child.on("message", (msg) => {
  console.log("Message from child:", msg);
});
console.log("Waiting for response...");

// child.js
process.on("message", (msg) => {
  console.log("Message received from parent:", msg);
  process.send({ response: "Hello from child!" });
});</code>

Best Practices for Managing Child Processes

Monitor system resources : Regularly check CPU, memory, and network usage to spot bottlenecks.

Set timeouts for long‑running processes : Use the timeout option in spawn() to automatically terminate overdue processes.

Implement graceful shutdown : Ensure child processes can close cleanly, releasing resources and handling termination signals.

Use appropriate kill signals : Prefer SIGTERM for graceful termination and fall back to SIGKILL if necessary.

Child Processes vs. Worker Threads

Worker threads (available from Node.js v10.5) provide true multithreading with shared memory, while child processes run in isolated memory spaces. Workers are lighter‑weight and ideal for frequent data exchange, whereas child processes are better for full isolation, running external scripts, or CPU‑intensive tasks.

When to Use Child Processes

Choose child processes when you need complete isolation, such as executing external scripts or handling CPU‑heavy workloads that could crash the parent.

When to Use Worker Threads

Use worker threads when tasks benefit from shared memory and low‑overhead communication, like parallel data processing or compute‑intensive algorithms.

Conclusion

The child_process module empowers Node.js applications to perform parallel tasks, run external commands, and manage subprocesses efficiently; understanding its methods and best practices can dramatically improve performance and scalability.

backend developmentNode.jsIPCParallel Processingchild_process
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

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.