The Node.js memory leak playbook — heap snapshots, clinic.js, and the four patterns we keep finding
May 21, 2026 · 1 min read · by Sudhanshu K.
Node.js memory leaks tend to look terrifying and usually aren't. The same four patterns appear in audit after audit: a Map/Set that grows unbounded, a closure that retains an unexpectedly large parent scope, event listeners attached but never removed, and an in-process cache without an eviction policy.
This is the diagnosis playbook we run on customer Node services that start eating memory week-on-week.
Heap snapshots — the only diagnosis that's not guesswork
import v8 from 'node:v8';
import fs from 'node:fs';
process.on('SIGUSR2', () => {
const file = `/tmp/heap-${Date.now()}.heapsnapshot`;
v8.writeHeapSnapshot(file);
console.log('wrote', file);
});Send SIGUSR2 to the process, get a snapshot, repeat after 30 minutes of traffic, diff the two in Chrome DevTools' Memory tab. The retained-objects column tells you exactly what's growing.
The full write-up covers:
- The four patterns and how each shows up in the heap snapshot diff
clinic.js doctorandclinic flamefor CPU + memory together--inspectand Chrome DevTools for live profiling in non-production- Running the leak detection against your own services in CI before production
- The cgroups + OOMKiller reading when the leak shipped anyway
- When the "leak" is actually V8's young generation not collecting fast enough (it isn't a leak)
Reach out if your Node service has been quietly growing and nobody's sure why.
Full article available
Read the full article