Skip to content

Expert · Performance and Node.js · topic 53 of 61 · 25 min

Memory and garbage collection

Explanation

JavaScript frees memory automatically with a garbage collector, which removes values that can no longer be reached from your code. A memory leak happens when you keep a reference you no longer need: a growing cache, a forgotten timer or event listener, or a closure holding big data. Leaks make long-running apps and servers slow down and crash.

Stack and heap in plain words

While a function runs, its small local values live in a fast, short-lived area called the stack; they vanish when the function returns. Objects, arrays, closures and strings live in a larger area called the heap, where they stay as long as something refers to them.

Garbage collection and reachability

You never free memory yourself in JavaScript. The engine's garbage collector (GC) regularly finds values that are no longer reachable, meaning no chain of references leads to them from the "roots" (global variables, the current call stack, active closures), and reuses their memory.

javascript
let user = { name: 'Asha', photo: new Array(1e6).fill(0) };
user = null;   // the big object is now unreachable → the GC can free it

const cache = [];
function remember(item) { cache.push(item); }   // everything pushed stays reachable forever

Common leaks

LeakWhy it leaksFix
Ever-growing cache or arrayA global Map/array keeps every entryLimit size (LRU), add expiry, or use WeakMap for object keys
Forgotten setIntervalThe timer and its closure live until clearedclearInterval when done (e.g. when a page or component closes)
Event listeners never removedThe element/handler and its closure stay aliveremoveEventListener, or AbortController signal
Closures holding big dataAn inner function keeps the whole outer variableKeep only the small part you need
Detached DOM nodesRemoved elements still referenced from JSDrop the references after removing
javascript
// Leaky: a "recent searches" cache that grows forever on a server
const recent = new Map();
function track(userId, query) {
  recent.set(`${userId}:${Date.now()}`, query);   // never deleted
}

// Fixed: keep only the newest 100 entries
const MAX = 100;
function trackSafe(userId, query) {
  recent.set(`${userId}:${Date.now()}`, query);
  if (recent.size > MAX) recent.delete(recent.keys().next().value);  // oldest first
}

WeakMap and WeakRef

A WeakMap keeps a value attached to an object key without keeping that key alive. When the object is no longer used elsewhere, its entry disappears automatically: perfect for "extra data about a DOM element or request object". WeakRef and FinalizationRegistry exist for advanced cases, but their timing is unpredictable, so avoid them unless you really need them.

Finding leaks

  1. Watch memory over time: in Node, process.memoryUsage().heapUsed; in the browser, the Memory panel of DevTools.
  2. Repeat an action many times (open and close a dialog 50 times). If memory keeps growing and never drops, something leaks.
  3. Take two heap snapshots (before and after) and compare which objects grew. For Node, run node --inspect and open chrome://inspect.
javascript
setInterval(() => {
  const mb = (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(1);
  console.log('heap used:', mb, 'MB');
}, 5000);
A quick memory log for a Node server.
Careful: Calling global.gc() or setting things to null everywhere is not the fix. Leaks are about references you forgot. Find what is still holding the data and remove that reference.
Think of it like this: The garbage collector is like a hostel warden clearing rooms: any room whose key no student holds anymore gets cleaned and given to someone new. A leak is a student who keeps the key to a room they no longer use, so the room is never freed.
Tip: Servers that slowly use more memory and need restarting every few days usually have a leak. Fix it rather than scheduling restarts.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Memory and garbage collection · 1/6

Memory

In this lesson you will learn how JavaScript frees memory and how memory leaks happen.

Prefer a video by a teacher? Find free videos on “javascript memory leaks garbage collection heap snapshot” on YouTube ↗

In real life: A chat dashboard that slowed down by evening

A customer-support dashboard got slower through the day. Each time an agent opened a chat, the code added a setInterval to poll for messages but never cleared it when the chat closed. By evening, hundreds of timers were running. Clearing the interval on close fixed it.

javascript
function openChat(id, poll) {
  const timer = setInterval(() => poll(id), 2000);
  return function closeChat() { clearInterval(timer); };  // the fix: always clean up
}
const close = openChat('C-17', (id) => {});
close();

Practice (0/2 done)

Task 1 · Code · Javascript

Write makeLimitedCache(max) that returns { set(key, value), get(key), size() }. When set makes the cache bigger than max, delete the OLDEST entry (Map keeps insertion order).

Task 2 · Code · Javascript

Write startPolling(fn, ms) that calls fn every ms milliseconds and returns a stop() function that clears the interval. The test checks that no calls happen after stop.

Quick quiz

Question 1

1.When can the garbage collector free an object?

Question 2

2.Which is a common memory leak?

Question 3

3.Why use a WeakMap to attach data to DOM elements?

Question 4

4.How can you spot a leak?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

When can the garbage collector free an object?

Answer: When no reachable reference points to it

Reachability decides what is kept.

Which is a common memory leak?

Answer: A setInterval that is never cleared

The timer and everything its callback refers to stay alive.

Why use a WeakMap to attach data to DOM elements?

Answer: Entries disappear when the element is gone

Weak keys do not keep the element alive.

How can you spot a leak?

Answer: Memory keeps growing while repeating an action and never drops

Steady growth after repeated actions is the classic sign.

Which is the default garbage collector in modern JDKs?Related

Answer: G1

G1 has been the default since Java 9.

From JVM memory and garbage collection

How does Rust decide when to free heap memory?Related

Answer: Ownership rules let the compiler insert the free at the right point

Rust frees a value when its owner goes out of scope, decided at compile time.

From Memory 101: the stack and the heap

Why use a WeakMap for a cache keyed by objects?Related

Answer: Entries do not keep the key objects alive

WeakMap entries disappear when the key object is no longer used elsewhere.

From Map and Set

Who frees heap memory in C?Related

Answer: The program, by calling free

There is no garbage collector.

From Stack and heap

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Performance and Node.js” before its exam: Node.js basics, Files and a tiny server in Node, Real project tooling.
  2. Module 11 exam: Performance and Node.js · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Interview preparation and career. 61 topics left in the course before the final exam.

← Previous: Performance thinking and Big-O