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.