Skip to content

What is a memory leak?

A memory leak happens when your program keeps objects in memory that it no longer needs — and the garbage collector cannot reclaim them because something still holds a reference.

In languages with manual memory management (C/C++), a leak means you forgot to free() memory. In JavaScript, you rarely call free() — the garbage collector (GC) reclaims unreachable objects automatically. So a JS “leak” really means: you accidentally kept something reachable.

Context Symptom
Browser tab Tab slows down, fans spin, mobile browser kills the tab
SPA / dashboard UI jank after hours of use without refresh
Node.js server RSS climbs over days; eventual OOM crash or container restart
Serverless Less common (short-lived), but warm instances can still leak
flowchart LR
  subgraph healthy [Healthy lifecycle]
    A[Allocate] --> B[Use]
    B --> C[Release references]
    C --> D[GC reclaims]
  end
  subgraph leak [Leak lifecycle]
    E[Allocate] --> F[Use]
    F --> G[Hidden reference remains]
    G --> H[GC cannot reclaim]
    H --> I[Memory grows]
  end
  • High baseline memory — a 200 MB Electron app isn’t leaking just because it’s large.
  • Temporary spikes — loading a big JSON response spikes heap, then GC may collect it.
  • GC hasn’t run yet — memory can look high between collection cycles.

A leak shows a sustained upward trend in retained memory while workload stays flat.

const cache = [];
function onMessage(msg) {
cache.push(msg); // never evicted — grows forever
}
const cache = new Map();
const MAX = 1000;
function onMessage(msg) {
cache.set(msg.id, msg);
if (cache.size > MAX) {
const oldest = cache.keys().next().value;
cache.delete(oldest);
}
}