Skip to main content

Parent and child process

1. The general principle

When you create a child process, Node.js gives you communication channels between it and the parent. These channels can be used for:

  • passing text data (stdin/stdout/stderr),
  • or two-way messaging via IPC (Inter-Process Communication).

2. Option 1: standard streams (stdin / stdout / stderr)

This is the classic way programs talk to each other on UNIX.

The parent writes data to child.stdin, and the child process reads it from process.stdin.

Example:

main.js

javascript
const { spawn } = require('child_process'); // Launch a child process (a Node.js script) const child = spawn('node', ['child.js']); // Write data to the child process's stdin child.stdin.write('42\n'); child.stdin.end(); // Read the reply from stdout child.stdout.on('data', (data) => { console.log('Reply from the child process:', data.toString()); });

child.js

javascript
process.stdin.on('data', (data) => { const num = parseInt(data.toString(), 10); const result = num * 2; process.stdout.write(`Result: ${result}\n`); });

How it works:

  • The parent writes to the child process's stdin.
  • The child reads it via process.stdin.
  • The result comes back through stdout.

Good for:

  • launching CLI commands, utilities, external programs;
  • interacting through standard streams (like a shell).

3. Option 2: IPC (Inter-Process Communication)

This is a built-in channel between Node.js processes, available only when the child process is created with fork().

It lets you pass JavaScript objects, not just text!

Example:

main.js

javascript
const { fork } = require('child_process'); // Launch a Node.js child process const child = fork('child.js'); // Send an object child.send({ task: 'calculate', number: 10 }); // Get the reply child.on('message', (msg) => { console.log('Reply from the child process:', msg); });

child.js

javascript
process.on('message', (msg) => { if (msg.task === 'calculate') { const result = msg.number * 2; process.send({ result }); } });

What happens:

  • fork() automatically creates an IPC channel.
  • child.send() sends a message to the child process.
  • process.on('message') in the child process receives it.
  • The reply comes back via process.send().

Good for:

  • exchanging JSON data;
  • distributed task-worker systems;
  • writing your own Node.js "workers".

4. Option 3: arguments at launch

Sometimes it's simpler to pass data once, when starting the process, for example through command-line arguments.

Example:

main.js

javascript
const { spawn } = require('child_process'); // Pass arguments to the process const child = spawn('node', ['child.js', '15']); child.stdout.on('data', (data) => { console.log('Reply:', data.toString()); });

child.js

javascript
const num = parseInt(process.argv[2], 10); console.log('Doubled value:', num * 2);

Here process.argv[2] holds the argument passed by the parent.

Good for:

  • a one-time set of parameters;
  • scripts and CLI commands.

5. Option 4: through the environment (env)

You can pass data to a child process through environment variables.

Example:

main.js

javascript
const { spawn } = require('child_process'); const child = spawn('node', ['child.js'], { env: { VALUE: 100 } });

child.js

javascript
console.log('VALUE from the environment:', process.env.VALUE);

Good for:

  • configuration, keys, secrets;
  • deployment and DevOps scenarios.

6. Comparing the ways to pass data

WayTransferData typeGood for
stdin / stdoutStreamsText / binary dataCLI programs, pipelines
child.send() / process.on('message')IPCJS objectsNode.js ↔ Node.js
Command-line argumentsOne-timeStringsSimple parameters
Environment variables (env)One-timeStringsConfiguration, secrets

7. An example of combined interaction

main.js

javascript
const { fork } = require('child_process'); const child = fork('child.js'); // Send data child.send({ action: 'start', payload: [1, 2, 3] }); // Receive replies while it's working child.on('message', (msg) => { console.log('Message from the child process:', msg); }); // End the process setTimeout(() => child.kill(), 2000);

child.js

javascript
process.on('message', (msg) => { if (msg.action === 'start') { const result = msg.payload.map(n => n * 2); process.send({ result }); } });

This is two-way, fully asynchronous communication, the parent and child can pass data to each other without blocking either thread.

Summary

ApproachToolDataTwo-wayNotes
stdin/stdout streamsspawn, execText / binaryYesUniversal, but needs serialization
The IPC channelforkJS objectsYesThe most convenient between Node.js processes
Argumentsspawn, execFileStringsNoA one-time transfer
Environment (env)spawn, execStringsNoPassing configuration

Conclusion:

A parent process can send data to a child in several ways:

  • through stdin (for external programs),
  • through IPC (send() / on('message')) for Node.js processes,
  • through arguments or environment variables for one-time parameters.

The most flexible, most "native" way for Node.js is IPC via fork(), because it lets you pass objects and events, not just text.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.