| Pattern |
Symptom |
Fix |
| Accidental global |
window.* grows |
delete, use let/const, modules |
setInterval |
CPU + heap over time |
clearInterval, store id |
| Detached DOM |
Detached * in snapshot |
Clear arrays holding elements |
| Listeners |
Handler count rises |
removeEventListener, AbortSignal |
| Closure |
Context retained |
Shrink captured scope |
Unbounded Map |
Entry count = requests |
LRU + TTL |
| EventEmitter |
MaxListenersExceededWarning |
off / once |
| Open stream |
external grows |
destroy(), pipeline() |
| Module cache |
RSS stair-step |
Bound or externalize store |
| Action |
Where |
| Heap snapshot |
DevTools → Memory |
| Force GC |
Memory → trash icon |
| Live heap |
performance.memory |
| Perf monitor |
More tools → Performance monitor |
| Action |
Command |
| Inspector |
node --inspect |
| Expose GC |
node --expose-gc |
| Snapshot |
v8.writeHeapSnapshot() |
| Metrics |
process.memoryUsage() |
| Panel |
Query |
| Working set |
container_memory_working_set_bytes{pod=~"app-.*"} |
| % of limit |
working_set / container_spec_memory_limit_bytes * 100 |
| Restarts |
increase(kube_pod_container_status_restarts_total[1h]) |
| Leak smell |
Memory staircase + flat rate(http_requests_total) |
Full walkthrough: Grafana & Kubernetes.
FATAL ERROR.*heap out of memory
MaxListenersExceededWarning