Node.js Performance
Clustering, streams, memory leak detection, caching, event loop monitoring.
nodejsperformancebackend
# Node.js Performance
## Cluster mode
```js
import cluster from 'node:cluster'
import { cpus } from 'node:os'
if (cluster.isPrimary) {
const numWorkers = cpus().length
for (let i = 0; i < numWorkers; i++) cluster.fork()
cluster.on('exit', (w) => {
console.log(`Worker ${w.process.pid} died, restarting...`)
cluster.fork()
})
} else {
// start server in each worker
app.listen(3000)
}
```
Or use PM2: `pm2 start app.js -i max`
## Streams for large data
```js
import { createReadStream } from 'node:fs'
import { pipeline } from 'node:stream/promises'
import { createGzip } from 'node:zlib'
// Stream file with gzip — never loads entire file into memory
await pipeline(
createReadStream('large.csv'),
createGzip(),
res // HTTP response
)
```
## Memory leak detection
```bash
# 1. Heap snapshot
node --inspect app.js
# Chrome DevTools → Memory → Take snapshot → Compare
# 2. Process memory tracking
setInterval(() => {
const { heapUsed, rss } = process.memoryUsage()
console.log(`Heap: ${(heapUsed/1e6).toFixed(1)}MB RSS: ${(rss/1e6).toFixed(1)}MB`)
}, 10000)
```
Common leaks: unbounded caches/Maps, uncleared intervals, unremoved listeners.
## Event loop monitoring
```js
import { monitorEventLoopDelay } from 'node:perf_hooks'
const h = monitorEventLoopDelay({ resolution: 20 })
h.enable()
setInterval(() => {
console.log(`EL p99: ${(h.percentile(99)/1e6).toFixed(1)}ms`)
h.reset()
}, 5000)
```
If p99 > 100ms, you have CPU-bound work blocking the loop.
## Caching
- In-memory LRU: `lru-cache` package.
- Redis for shared state across workers.
- HTTP caching headers (ETag, Cache-Control) for API responses.
## Quick wins
- Use `JSON.parse()` for large object literals instead of JS object syntax.
- Prefer `Buffer.allocUnsafe()` when filling immediately.
- Use `Promise.all()` for independent async ops.
- Avoid `sync` file/crypto methods in hot paths.
API: /api/skills/node-performance