In short
Sometimes the best tool for a job isn't JavaScript: git, ffmpeg, a Python script. Child processes let your Node app run other programs and read what they print.
Node's ability to spawn separate OS processes — to run shell commands, other scripts, or CPU-heavy work — without blocking the main event loop.

Think of it like this
The head chef sends a helper
The head chef doesn't leave the stove to buy coriander. She sends a helper with a bag and a list, keeps cooking, and the helper comes back with the goods or with bad news. A child process is that helper: a separate program your app starts and waits on.
Watch it happen
Running git from Node
spawn("git", ["log"])
1/6Node asks the OS to start git as a separate process with its own memory.
The big ideas
What you need to know
spawn streams output
spawn gives you stdout and stderr as streams. Good for long-running commands or lots of output.
execFile collects it
execFile waits and hands you all the output at once. Handy for short commands like git log.
Avoid the shell with user input
exec runs a shell, so ; or && in input can start extra commands. Prefer execFile or spawn with an argument array.
fork for Node scripts
fork starts another Node script with a built-in message channel, using send() and the 'message' event.
See it in code
Walk through the code
1import { spawn, execFile } from "node:child_process";2import { promisify } from "node:util";3 4const run = promisify(execFile);5const { stdout } = await run("git", ["log", "--oneline", "-5"]);6console.log(stdout);7 8const child = spawn("ping", ["-c", "3", "example.com"]);9child.stdout.on("data", (chunk) => process.stdout.write(chunk));10child.stderr.on("data", (chunk) => process.stderr.write(chunk));11child.on("close", (code) => console.log("ping exited with code", code));1/4execFile, promisified: run git, wait for it to finish, get all of stdout as one string.
Save as child.mjs inside any Git repo and run it. ping -c works on macOS and Linux; on Windows use ping -n 3 instead.
Save yourself the pain
Common mistakes
Oops
Building a command string from user input, like exec("convert " + req.query.file + " out.png").
Do this instead
A file name like a.png; rm -rf ~ runs a second command. Use execFile or spawn with an arguments array, which skips the shell.
Oops
Ignoring the exit code and assuming the command worked.
Do this instead
Check the code in the 'close' event. Promisified execFile throws automatically when the code isn't 0.
Your mission
A git stats endpoint
Quick check
Why is execFile("ls", [userInput]) safer than exec("ls " + userInput)?
Go deeper
- 1Use `child_process.exec` to run a shell command from a Node script.
- 2Learn the difference between `spawn`, `exec`, and `fork`.
- 3Understand when to offload CPU-intensive work to a child process instead of blocking the event loop.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.