Common JavaScript Memory Leaks

Common leak patterns include accidentally retained global references, event listeners that remain attached unnecessarily, timers that keep closures alive, caches that grow without bounds, and long-lived data structures retaining objects that should have been released.

Closures themselves are not memory leaks. They become problematic when a long-lived object retains a closure that in turn retains a large object graph unnecessarily.

An Unbounded Cache
const cache = new Map();

function remember(key, value) {
  cache.set(key, value);
}

// If keys continuously grow and entries are never removed,
// the cache can retain more and more memory.
💡 The Map itself remains reachable, so entries remain reachable through it. An unbounded cache can therefore create sustained memory growth.
Key Takeaways
  • Closures are not inherently memory leaks.
  • Long-lived references can retain large object graphs.
  • Caches should have eviction or bounded lifetime when appropriate.
Knowledge Check

Which pattern can cause a memory leak?