What happens if a browser tab reaches its memory limit
The browser will discard or crash the tab. Chrome shows the 'Aw, Snap!' page or silently kills background tabs to reclaim memory (tab discarding). Tabs in different processes don't take each other down (Site Isolation). Common causes: leaks (event listeners, detached DOM, big closures), unbounded caches, large textures/canvases, huge in-memory data.
Browsers cap per-tab memory and react fast when you hit it.
What actually happens
- Tab discarding — Chrome may suspend background tabs that aren't visible, freeing memory; when reactivated, they reload from scratch (state loss unless restored from session/storage).
- Page crash — foreground tab exceeds the renderer process limit → "Aw, Snap!" / "Page Unresponsive". The renderer process is killed; the rest of the browser survives.
- Allocation failures —
new ArrayBuffer(huge)throwsRangeError;Image/Canvasmay fail to allocate. - Performance degradation — major GC pauses become long and frequent before the crash.
Per-process isolation
With Site Isolation (Chrome by default), each cross-site frame runs in its own process. One tab crashing doesn't crash siblings; an iframe can crash independently of its parent.
Common causes of leaks
| Cause | Fix |
|---|---|
| Event listeners never removed | Use AbortController signal; cleanup in useEffect return; addEventListener + removeEventListener paired. |
| Detached DOM held by JS refs | Null refs in cleanup. |
| Long-lived closures over large objects | Drop refs after use. |
| Unbounded caches / Maps | Cap size; LRU eviction. |
| Subscriptions / intervals never cleared | Pair every setInterval / setTimeout / addEventListener with cleanup. |
| Canvas / video / WebGL resources not disposed | canvas.width = 0; release WebGL textures. |
| React: stale state in closures, useMemo deps with big values | Tighten deps; profile. |
Detection tools
- DevTools Memory panel — heap snapshots, allocation timelines, retainers.
- Performance Monitor — JS heap size live.
performance.memory(Chrome only, behind a flag now).- Detached DOM nodes report in Memory panel.
In code
// Memory-safe event listener
const ac = new AbortController();
window.addEventListener("resize", onResize, { signal: ac.signal });
// later:
ac.abort(); // removes all listeners attached with this signal// Bounded cache
class LRU {
constructor(cap) { this.cap = cap; this.m = new Map(); }
get(k) { const v = this.m.get(k); if (v !== undefined) { this.m.delete(k); this.m.set(k, v); } return v; }
set(k, v) { if (this.m.has(k)) this.m.delete(k); else if (this.m.size >= this.cap) this.m.delete(this.m.keys().next().value); this.m.set(k, v); }
}Defensive design
- Pagination / virtualization for large lists (see [[build-a-virtualized-list-for-very-large-datasets]]).
- Stream large downloads instead of loading into one Blob.
- Web Workers for big compute — separate heap, terminate freely.
- OffscreenCanvas for image work.
- Persist + rehydrate instead of keeping everything in memory.
Interview framing
"Chrome's renderer process has a memory cap (varies by platform — gigs on desktop, much less on mobile). Hitting it = tab discard for background tabs, or 'Aw, Snap!' for foreground. Site Isolation keeps the rest of the browser alive. Most real issues are leaks — listeners never removed, intervals never cleared, detached DOM held by JS, unbounded caches. The tools are DevTools Memory panel for heap snapshots and detached DOM, plus the Performance Monitor for live tracking. Defensive design: virtualize lists, stream large downloads, move heavy work to Workers, cap caches."
Follow-up questions
- •What's Site Isolation?
- •How would you find a memory leak in production?
- •How does AbortController help with cleanup?
Common mistakes
- •Forgetting to remove event listeners.
- •Holding refs to detached DOM.
- •Unbounded in-memory caches.
Performance considerations
- •Long GC pauses precede crashes. Watch heap size in Performance Monitor for early signs.
Edge cases
- •iOS Safari has much tighter limits than desktop.
- •WebGL contexts have a small per-page cap.
- •ServiceWorker / cache storage limits separate from heap.
Real-world examples
- •Long-running SPAs (Slack web after days), large data tables, heavy editor apps.