What you'll learn
Move CPU-heavy JavaScript to a bounded worker-thread pool and launch external programs through explicit arguments and lifecycle controls. Parallelism helps only when work, communication, and failure are budgeted.
By the end of this lesson, you'll be able to:
- Choose workers, processes, or ordinary async I/O
- Build a reusable worker pool
- Transfer data efficiently
- Control subprocess input, timeouts, and exit
Core mental model
Node.js becomes easier when you separate the JavaScript language from the runtime and the operating-system capabilities it exposes. Use this table as a decision guide.
| Concept | What it means | Decision rule |
|---|---|---|
| Worker thread | A separate JavaScript isolate in one process | Use for substantial CPU work, not normal I/O |
| Child process | An isolated OS process or external executable | Use for tools or stronger failure boundaries |
| Pool | A bounded reusable set of executors | Avoid startup cost and unbounded parallelism per request |
Professional workflow
Build and verify Node.js programs from the terminal in small, observable steps.
- Define the parallel execution boundary boundary: inputs, outputs, invariants, ownership, and expected failures.
- Design the data or message contract before choosing implementation details.
- Implement the smallest correct path with dependencies passed explicitly.
- Add validation, failure translation, cleanup, and concurrency behavior.
- Verify the boundary with realistic data and at least one adversarial case.
- Measure or observe the behavior before optimizing or extracting abstractions.
Keep the feedback loop short
Guided code lab
Run an external tool without a shell
execFile receives arguments separately, caps output, and can be aborted; untrusted text never becomes shell syntax.
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const runFile = promisify(execFile);
await runFile('ffmpeg', ['-i', inputPath, '-frames:v', '1', outputPath], {
timeout: 15_000,
maxBuffer: 1024 * 1024,
windowsHide: true,
});Production practice
Contract
Every parallel task defines serializable input/output, maximum concurrency, timeout, cancellation, memory budget, and failure translation.
Verification
Test executor crash, timeout, oversized message/output, queue saturation, cancellation, retries, and clean process shutdown.
Operations
Reuse a bounded pool, track queue time and execution time, recycle unhealthy workers, and isolate temporary files.
Common failure mode
Independent workshop
Offload image metadata analysis to a worker pool with safe queue limits.
Your finished workshop must include:
- CPU/I/O decision note
- Bounded pool
- Message contract
- Timeout/cancellation
- Crash recovery
- Saturation metrics
Definition of done
Recap & quick check
Key takeaways
- Workers serve CPU work
- Processes improve isolation
- Pools bound concurrency
- Messages have cost
- Shells expand injection risk
Quick check
1. What work best fits worker_threads?
2. Why pool workers?
3. Why prefer execFile for a known binary?
Next: WebSockets & Real-Time Systems