Angular Memory Leaks: A Guide for Developers & Decision-Makers to Optimize Performance

Angular Memory Leaks: A Guide for Developers & Decision-Makers to Optimize Performance

Last week I worked on memory leaks in our Angular application. Today is not about why memory leaks were introduced, but rather about how to find and fix them.

Memory leaks were identified using Chrome DevTools. The Memory tab is especially useful for this. I repeatedly followed these steps:

  1. Take snapshot (1)
  2. Perform a potential memory leak interaction
  3. Go back
  4. Take snapshot (2)
  5. Perform a potential memory leak interaction
  6. Go back
  7. Take snapshot (3)

It’s best to do this in incognito mode, remove all console.log / warn / debug / info logs to avoid console retainers. Ideally, use a production build—but that usually means losing source maps and therefore traceability.

Snapshot comparison

Snapshot 1 → 2: 🙈

  • Not very useful to compare, since the first interaction initializes long-running services and lazy modules.

Snapshot 2 → 3: ✅

  • Compare both snapshots in Comparison mode. These should be very similar. All components created during the interaction should have been destroyed.
  • Next, filter for "Component" or your HTML tag prefix (e.g. "app-"). There should be no components left with a positive delta between New and Deleted.
  • If you select a leaking component, the Retainers section shows why it wasn’t cleaned up. Sometimes this is very helpful (e.g. missing event listener cleanup), but sometimes it’s hard to interpret. You work through it step by step.
  • It’s also worth checking other sections beyond components—for example caches that keep growing and are never cleared.

🔁 Tip: Repeat the leaking scenario multiple times. This makes it easier to detect patterns. For example, if you run it 5 times, look for deltas like 5, 10, 15… since components may be instantiated multiple times.


Common sources of memory leaks

  • Observables that are not unsubscribed
  • setInterval / setTimeout without cleanup
  • Event listeners on window or document that are never removed
  • References to DOM elements that were removed but are still held in variables
  • RxJS Subject / BehaviorSubject not completed (better to complete once too often than not at all)
  • Closures in callbacks (e.g. callbacks referencing this)
  • MutationObserver, ResizeObserver, IntersectionObserver without calling disconnect
  • Ever-growing caches


Another important aspect is presenting the results. 📈

For this, I created a Playwright performance test that runs the leaking scenario 100 times and reads the memory heap after each iteration via the Chrome DevTools Protocol (CDP). From that, I generated a JSON file and used Chart.js to build a chart (the one from the article background)

I’m very proud of the result. Any experienced web developer knows that memory leaks are a difficult topic—and the achieved result is excellent.

A normal heap flow looks like a sawtooth pattern (similar to stop-and-go traffic): memory grows, then the garbage collector runs and frees it, and this repeats indefinitely. With memory leaks, however, you get a growing sawtooth pattern—more like a staircase.


❓ I’m pretty sure that almost every larger web project has memory leaks. How do you deal with them? Do you have tests to detect them? I’d love to hear about your experiences. ❓❓

Written with ❤️ by human. Translated by AI.

To view or add a comment, sign in

Others also viewed

Explore content categories