0Pricing
Node.js Backend Development Bootcamp · Lesson

Detecting and Fixing Common Leak Patterns

Track down leaking closures, unbounded caches, and lingering listeners that grow heap over time.

What a Real Leak Looks Like

A memory leak in Node.js is not when memory goes up — it is when memory goes up and never comes back down across GC cycles. The V8 heap grows, old-space stays retained, and eventually you hit the default --max-old-space-size ceiling and the process is OOM-killed.

  • Normal: heap saws up and down as GC reclaims short-lived objects.
  • Leak: the saw-tooth baseline trends upward over hours, even at steady traffic.

In this lesson we hunt the three classic backend offenders: leaking closures, unbounded caches, and lingering event listeners.

Reading the Heap with process.memoryUsage()

Your first cheap signal is process.memoryUsage(). Watch heapUsed over time. If it climbs monotonically under constant load, you have a retention problem.

The snippet below simulates a leak by pushing into a module-level array and logs heap growth every interval — a standalone reproduction you can run.

const leaky = [];

function tick(i) {
  // Each call retains a 10k-element array forever.
  leaky.push(new Array(10_000).fill(i));
  const { heapUsed } = process.memoryUsage();
  console.log(`tick ${i}: heapUsed=${(heapUsed / 1024 / 1024).toFixed(1)} MB, retained=${leaky.length}`);
}

for (let i = 1; i <= 5; i++) tick(i);
console.log('Heap keeps growing because `leaky` is never cleared.');

All lessons in this course

  1. The V8 Heap, Generational GC, and Object Lifetimes
  2. Capturing and Comparing Heap Snapshots
  3. CPU Profiling and Flame Graphs for Hot Paths
  4. Detecting and Fixing Common Leak Patterns
← Back to Node.js Backend Development Bootcamp