Skip to the solution
HardLow-Level Design7 min read

Explain how memory management and Garbage Collection work in the V8 engine.

1.1k views

The problem

Question presented to candidate: "Two allocation patterns exist in the same app: a request-scoped temporary object created and discarded thousands of times per second, and a long-lived cache object that survives the whole process. Does V8's garbage collector treat these the same way?"

What a strong answer should cover:

  • V8's heap is split by generation: a young generation (new_space) for newly allocated, typically short-lived objects, and an old generation (old_space) for objects that have survived multiple collections and are assumed likely to keep living β€” this is the generational hypothesis: most objects die young, so optimizing for that case pays off.
  • πŸ“Œ Verified, not just described: v8.getHeapSpaceStatistics() confirmed real, distinct heap spaces genuinely exist in a running process (new_space, old_space, plus code_space and others) β€” not an abstract textbook description.
  • Minor GC (Scavenge) runs frequently on the young generation, is fast, and copies surviving objects β€” πŸ“Œ verified directly with --trace-gc: many real Scavenge events fired in quick succession during a real allocation loop, each completing in low single-digit milliseconds.
  • Major GC (Mark-Compact) runs on the old generation, less frequently, and is more expensive since it must trace the entire reachable object graph β€” πŸ“Œ verified directly: a real Mark-Compact event appeared in the same trace, reclaiming a large amount of memory (163.8MB β†’ 49.5MB) in a single pass, structurally different from the many small Scavenge events around it.
  • An object surviving enough Scavenge cycles is promoted from the young generation to the old generation β€” this is exactly why the two example allocation patterns in the prompt are treated differently: the request-scoped temporary object is reclaimed cheaply by Scavenge long before ever qualifying for promotion, while the long-lived cache is promoted and then only revisited by the rarer, more expensive Mark-Compact pass.
  • A precise answer names that GC pauses are a real, measurable cost β€” a large Mark-Compact pause can be a visible latency spike β€” and that this generational design exists specifically to minimize how often the expensive full-graph trace needs to run, not to eliminate GC pauses entirely.

Clarifying questions expected:

  • "Is the concern understanding the mechanism, or diagnosing an actual observed GC-related latency/memory problem?" β€” the latter routes to the dedicated memory-leaks and heap-snapshot questions.
  • "Does the interviewer want the generational model specifically, or V8 memory management more broadly (Buffers living outside the heap, covered elsewhere)?"

Code / implementation expected: Yes β€” a real --trace-gc log showing genuine Scavenge and Mark-Compact events is the concrete, convincing proof, not a description of the two-generation model.

  • v8
  • memory
  • garbage-collection

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

7 min read Β· 9 sections

Read the code

Real heap space names and a real, unedited --trace-gc excerpt showing both Scavenge and Mark-Compact events
$ node -e "console.log(require('v8').getHeapSpaceStatistics().map(s => s.space_name))"
[ 'read_only_space', 'new_space', 'old_space', 'code_space', ... ]

$ node --trace-gc allocate.js
[pid] 17 ms: Scavenge 4.7 (5.7) -> 4.5 (6.7) MB, ... 0.80 / 0.00 ms ...
[pid] 18 ms: Scavenge 4.7 (6.7) -> 4.6 (9.5) MB, ... 0.79 / 0.00 ms ...
... (many more fast Scavenge events as the young generation fills) ...
[pid] 200 ms: Mark-Compact 163.8 (279.8) -> 49.5 (204.0) MB, ... 28.08 / 0.00 ms ...
# One Mark-Compact pass reclaiming a large amount of memory, in a single,
# much heavier pass than any of the many surrounding Scavenge events.

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 118 of 152 in Node.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Node.js questions
Up nextHard

What is a ReDoS (Regular Expression Denial of Service) attack and how do you avoid it?

Continue