In this lesson, you will learn how to monitor memory that resides outside the V8 heap, specifically the memory allocated by native C++ addons that the V8 Garbage Collector cannot directly see or manage.
The Invisible Footprint
When you use Node.js modules that interface with native C++ code (like sharp for image processing, node-sqlite3, or custom N-API addons), these libraries often allocate memory using standard malloc or new calls. Because this memory exists in the system's address space rather than the V8 managed heap, the Garbage Collector (GC) is "blind" to it. It won't trigger a collection cycle based on this external pressure, potentially leading to a process crash via Out of Memory errors even when process.memoryUsage().heapUsed appears perfectly healthy.
Quantifying External Pressure
To monitor this, we rely on process.memoryUsage(), which provides an external field. This value represents the memory held by C++ objects bound to JavaScript objects. When we create objects that rely on external buffers—such as Buffer.allocUnsafe or native addon data—V8 attempts to track this via v8::Isolate::AdjustAmountOfExternalAllocatedMemory.
Consider this scenario where we simulate an external allocation:
// Monitoring external memory growth
const initial = process.memoryUsage().external;
// Simulating a native buffer allocation
const buffer = Buffer.allocUnsafe(1024 * 1024 * 50); // 50MB
const current = process.memoryUsage().external;
console.log(`External memory increase: ${(current - initial) / 1024 / 1024} MB`);
When to Intervene
If your external memory metric shows a steady upward trend while your heap remains flat, you are likely dealing with an "external leak." This often happens when native objects are created but their JavaScript wrappers are not correctly associated with the native resource, or the C++ side fails to call the appropriate destructors.
To mitigate this, ensure your native addons are correctly reporting their memory usage to V8 using the v8::Isolate adjustment APIs. By explicitly telling V8 how much memory you have allocated externally, you trigger the GC to run more frequently, effectively "telling" V8 that the process is under higher memory pressure than the heap alone suggests.
Key Takeaway: Since the V8 Garbage Collector cannot see native allocations, you must track process.memoryUsage().external to detect memory growth in native addons and proactively report those allocations to V8 to prevent silent system-level memory exhaustion.