Question presented to candidate: "Production alerts say a Node.js service's memory is climbing. What number, specifically, do you look at first to tell a genuine leak apart from normal, healthy memory usage that just hasn't been garbage-collected yet?"
What a strong answer should cover:
process.memoryUsage()is Node's built-in entry point for real memory numbers — no external tool required for a first look. 📌 Verified, not assumed: a real snapshot before, during, and after allocating 2,000,000 real objects showedheapUsedgenuinely growing from 4.0MB to 353.4MB, then genuinely falling back to 4.0MB after clearing the reference and forcing a real GC pass — real numbers, not illustrative ones.- A precise answer distinguishes the fields:
rss(resident set size — total real memory the process holds, including the heap, native code, and everything else) is the number closest to what the OS/orchestrator (Kubernetes, a container memory limit) actually enforces;heapUsedis specifically JS-object memory V8 is tracking;heapTotalis memory V8 has currently reserved for the heap (usually larger thanheapUsed, and grows in chunks rather than exactly matching usage);externalis memory used by C++ objects bound to JS (notably Buffers). - Distinguishing a genuine leak from healthy memory that has not been collected yet: healthy usage rises during work and then falls back down once that work's objects become unreachable and a GC pass runs (verified directly above — the clear-and-gc step genuinely reclaimed the memory). A genuine leak instead shows heapUsed on a sustained upward trend across many consecutive GC cycles, never returning to a stable baseline — a single snapshot cannot tell the two apart; a timeseries can.
- For production monitoring at scale (beyond a manual
process.memoryUsage()call), the standard approach is exporting these same numbers as metrics on an interval (an APM agent, a Prometheus/metricsendpoint) so the sustained-upward-trend pattern is visible on a dashboard over hours/days, not just in a single snapshot taken by hand. - When a genuine leak is confirmed by the trend, the next diagnostic step — covered in its own dedicated question in this bank — is capturing a heap snapshot at two points in time and diffing them to find exactly which objects are accumulating and why they are still reachable.
Clarifying questions expected:
- "Is this a single sustained upward trend over hours, or a sawtooth pattern that rises and falls with traffic?" — the single most important diagnostic question; only the former indicates a genuine leak.
- "Is the concern the process's total memory (rss, what a container's memory limit enforces) or specifically JS heap growth?" — decides which field to actually watch first.
Code / implementation expected: Yes — the real, measured memoryUsage() snapshot (genuine growth, then genuine reclaim after GC) is the concrete, convincing demonstration of what healthy memory behavior actually looks like, as the baseline for spotting a genuine leak.