Troubleshooting guide · performance · Published 2026-08-16 · 4 min read

JavaScript memory leaks and how to fix them

Find and fix JavaScript memory leaks in the browser: detached DOM nodes, closure references and un-cleared intervals, using the DevTools heap tools.

What a browser leak is

A JavaScript memory leak is memory the page keeps holding that it no longer needs, so the browser's usage climbs steadily over time instead of stabilising. Because the browser must eventually garbage-collect unreachable memory, a true leak means something is still reachable that should not be: a reference chain keeps an object, an event listener, or a DOM node alive when the page no longer uses it. The symptoms are a tab that gets slower, and in the worst case a reload or a hang, as the growing heap forces increasingly aggressive garbage collection.

A leak is usually not an error message; it is a growth trend. Fixing it is about finding the reference that keeps the object alive and removing it. This is different from a one-off peak, such as the heap exhaustion from a single large allocation that a process hits and crashes on, which is a spike rather than a slow accumulation.

The common causes

Finding and fixing it

  1. Record a heap snapshot and the delta. Open DevTools Performance, record memory against a workload, then take two heap snapshots and compare allocations over time. Because a leak is a trend, the tell is a baseline that keeps rising through repeated identical work.
  2. Look for detached nodes and retained objects. In the heap snapshot, expand detached nodes to see what keeps a removed element alive, and inspect the retaining paths to identify the variable or listener holding it. Trail the reference chain to the root object that should have been released.
  3. Remove listeners and intervals in the cleanup path. When a view or component is torn down, remove its listeners and clear its intervals, matching every put with a remove:
window.addEventListener("scroll", handler);
// later, on teardown:
window.removeEventListener("scroll", handler);
clearInterval(timer);
  1. Release closures over large data. When a long-lived callback needs only a field, copy the small value instead of capturing the whole object, so the big object can be collected. Keep caches bounded with a size limit or expiry rather than unbounded.
  2. Re-measure the trend. Re-run the workload and confirm the heap returns to a stable level instead of climbing. Integrate this as part of the web performance audit, and check it on page tear-down flows rather than only on first load.

Memory pressure also explains interaction that degrades over a session. If heavy main-thread work is the root rather than a reference leak, the off-main-thread and bundle reduction guides address the workload itself. The fix for a genuine leak is nearly always a removed reference, which is why the message to keep in mind is: a page that holds what it no longer needs is a page that will slowly degrade until it cannot.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services