Measure, Then Optimize — Where Node Actually Hurts
Performance
Find the slow parts before guessing. Use the Inspector profiler, clinic.js, and basic perf hooks.
What you'll learn
- Use perf_hooks for quick timings
- Profile with the Inspector
- Recognize common Node perf bugs
The first rule: measure before optimizing. Most perf “fixes” target the wrong thing.
Quick Timing — perf_hooks
import { performance } from "node:perf_hooks";
const start = performance.now();
await expensiveThing();
console.log(`took ${performance.now() - start}ms`); For higher-resolution: process.hrtime.bigint() (nanoseconds).
CPU Profiling
node --inspect server.mjs In chrome://inspect → Profiler tab → Start. Click around your
app for a few seconds. Stop. Chrome shows flame charts of where CPU
time went.
The “biggest blob in the flame chart” is where to look first.
clinic.js — Quick Diagnoses
npm install -g clinic
clinic doctor -- node server.mjs doctor watches your app, fires synthetic load, and tells you the
likely problem class — CPU-bound? Event loop blocked? GC pressure?
clinic flame produces flame graphs. clinic bubbleprof shows
async operations.
Common Node Perf Bugs
| Symptom | Likely cause |
|---|---|
| High p99 latency, low CPU | Event loop blocked somewhere — find sync IO or heavy loops |
| Memory grows over time | Memory leak — usually a closure capturing references in an array/map |
| Spike in latency every minute | GC pause — high allocation rate |
| Slow boot, fast steady-state | Loading too much at startup; lazy-load |
| Lots of context switches | Too many worker threads or child processes |
Practical Wins
- Use streams for large IO instead of
readFile - Use
Promise.allfor independent async ops - Don’t
awaitinside aforloop if you canPromise.allthe map results - Profile big endpoints — surprising hotspots are common
- Pin Node version — perf can change between versions
When To Care
Don’t pre-optimize. Build the feature. If it’s slow in production (or in a load test), profile and fix. Otherwise: clear code beats clever code.
Deployment →