A growing Node.js process is not automatically leaking JavaScript objects, and a clean-looking heap snapshot does not prove fragmentation. Start by separating the memory measurements and recording the workload that produced them.
This guide describes an investigation method rather than an unverified production incident.
Distinguish the Measurements
RSS describes resident process memory, including more than the JavaScript heap. heapUsed and heapTotal describe V8 heap usage; external accounts for native allocations associated with JavaScript objects. arrayBuffers includes Buffer storage and is already included in external, so adding those two values double-counts memory.
Node specifically documents that glibc allocator fragmentation can produce rising RSS despite stable heapTotal on affected systems. That is a possible explanation, not a diagnosis from RSS alone. Node’s process documentation defines these measurements.
Take a Comparable Sample
This function uses the documented getHeapStatistics API:
import { memoryUsage } from "node:process";
import { getHeapStatistics } from "node:v8";
export function memorySample() {
const usage = memoryUsage();
const heap = getHeapStatistics();
const mib = value => Number((value / 1024 / 1024).toFixed(2));
return {
timestamp: new Date().toISOString(),
rssMiB: mib(usage.rss),
heapUsedMiB: mib(usage.heapUsed),
heapTotalMiB: mib(usage.heapTotal),
externalMiB: mib(usage.external),
arrayBuffersMiB: mib(usage.arrayBuffers),
heapLimitMiB: mib(heap.heap_size_limit),
};
}
Call it at a modest interval from existing monitoring or during a controlled test. The V8 API reference documents the returned heap statistics. This snapshot records quantities, not the reason allocations remain resident.
Do not label heapUsed divided by heapTotal a fragmentation detector. V8 reserves space, grows its heap and collects at different points in the workload. A ratio below 0.4 does not establish fragmentation, just as a ratio above 0.7 does not prove health.
Match the Investigation to the Pattern
| Pattern under a repeated workload | Useful next evidence |
|---|---|
| Retained JavaScript objects grow | Comparable heap snapshots and retaining paths |
| External or Buffer memory grows | Binary payload lifetime, streams, native modules and references |
| RSS grows while heap and external figures stabilize | Allocator and operating-system evidence |
| Growth tracks legitimate cache entries | Capacity, eviction and expected working set |
| Peaks occur with larger requests | Input limits, copies and concurrent in-flight work |
Compare the same operation with a fixed payload set, concurrency and runtime version. Include an idle period and observe whether the working set stabilizes. One sample during active allocation is not comparable to another taken after collection.
Avoid Fixes That Hide the Cause
An object pool can retain more memory than ordinary allocation if it has no capacity limit. Reusing request objects can also keep references alive accidentally. Introduce pooling only when measurement shows a benefit and ownership is explicit.
A V8 heap limit is not a process RSS limit. Native allocations and other process memory still matter. Changing heap flags may alter collection behavior without resolving the responsible allocation pattern.
Scheduled restarts can temporarily contain a problem, but they need graceful request draining and should not be presented as evidence that the leak or fragmentation was fixed.
Record a Defensible Result
A useful report states the runtime and operating system, workload, memory categories, retained-object evidence and the measured effect of one change. If allocator fragmentation remains a hypothesis, say so.
The practical goal is a bounded working set under the expected workload, with enough evidence to explain why the process reaches that size.

Sardar Mukhshaf
Full-Stack & DevOps Engineer
I build scalable web applications, secure backend systems, and production-ready cloud infrastructure. My engineering focus spans interface design, API architecture, deployment pipelines, and observability. Follow for more deep dives into system architecture, performance engineering, and emerging technologies.
More from the practice
Keep the useful ideas close.
Follow new articles with your preferred RSS reader.
Open the RSS feed ↗


