intermediate
CPU-bound vs I/O-bound work
Classify bottlenecks so async I/O, worker threads, queues, caching, batching, or horizontal scaling solve the right problem.
Node excels at concurrent I/O-bound work — many waits on network/disk overlap on one thread. CPU-bound JavaScript (JSON parsing huge payloads, image resize in JS, complex aggregation) blocks the event loop and hurts all clients.
| Bottleneck | Symptoms | Mitigations | |------------|----------|-------------| | I/O-bound | Waiting on DB/API/disk | Async APIs, pooling, caching, batching | | CPU-bound (JS) | Event loop delay spikes | Worker threads, native addons, offload service | | CPU-bound (sync libuv) | Thread pool queue lag | Fewer concurrent ops, native code, larger pool cautiously |
Measure before choosing: event loop utilization, `perf_hooks` delay, p99 latency under load.
// Bad: blocks all requests for 200ms
const sorted = hugeArray.sort(expensiveCompare);
// Better: worker or incremental chunking with setImmediate yields
On interviews: classify a given workload; explain why more cluster workers help throughput but not single-request CPU time per worker.
Common pitfalls: `JSON.parse` on megabyte bodies on main thread; regex catastrophic backtracking; scaling replicas without fixing loop blockers.
The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.
Checklist:
- Profile to classify CPU vs I/O.
- Move heavy compute off main thread.
- Cache idempotent read-heavy I/O.
- Set payload size limits at edge.