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
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
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
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
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
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
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
const { spawn } = require('child_process');
const child = spawn('node', ['child.js'], {
env: { VALUE: 100 }
});child.js
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
| Way | Transfer | Data type | Good for |
|---|---|---|---|
stdin / stdout | Streams | Text / binary data | CLI programs, pipelines |
child.send() / process.on('message') | IPC | JS objects | Node.js ↔ Node.js |
| Command-line arguments | One-time | Strings | Simple parameters |
Environment variables (env) | One-time | Strings | Configuration, secrets |
7. An example of combined interaction
main.js
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
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
| Approach | Tool | Data | Two-way | Notes |
|---|---|---|---|---|
| stdin/stdout streams | spawn, exec | Text / binary | Yes | Universal, but needs serialization |
| The IPC channel | fork | JS objects | Yes | The most convenient between Node.js processes |
| Arguments | spawn, execFile | Strings | No | A one-time transfer |
| Environment (env) | spawn, exec | Strings | No | Passing 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 readyA concise answer to help you respond confidently on this topic during an interview.