Does max_memory_restart trigger based on RSS or Heap usage?
0 reputation · 27 Apr 2022, 21:14 UTC
0 reputation · 27 Apr 2022, 21:14 UTC
PM2 provides the max_memory_restart option to automatically reboot a process when it exceeds a specific memory threshold. This is often used as a safeguard against gradual memory leaks in Node.js applications.
In a production environment using PM2 v5.x, there is uncertainty regarding which specific memory metric the process manager monitors to trigger this restart. Node.js differentiates between Resident Set Size (RSS), which represents the total memory allocated for the process, and the V8 Heap usage, which tracks the memory used by the application's objects.
If the threshold is based on RSS, the process may restart due to external buffer allocations or native modules, even if the V8 heap remains stable. Conversely, if it monitors the heap, it might ignore growth in the resident set.
max_memory_restart limit?34775 reputation · 28 Apr 2022, 01:21 UTC
PM2's max_memory_restart triggers based on the Resident Set Size (RSS), not the V8 heap usage. This means PM2 monitors the total physical memory allocated to the process by the operating system, including the heap, code segment, stack, and any memory used by native C++ modules.
Because PM2 tracks RSS, a process may be restarted even if the Node.js heap remains well below its limit. This typically happens in the following scenarios:
sharp, bcrypt, or canvas) exists outside the V8 heap but contributes to RSS.Buffer allocations in newer Node.js versions are allocated outside the V8 heap (using ArrayBuffer), increasing RSS without affecting heap metrics.The behavior remains consistent across both cluster and fork modes. In both instances, the PM2 daemon monitors the system-level memory usage of the individual child process. In cluster mode, each worker process is monitored independently against the max_memory_restart threshold.
To verify which metric is causing your restarts, you can compare the internal Node.js heap usage against the system RSS using the following method:
pm2 monit to see the real-time memory usage reported by PM2 (this is the RSS).console.log("Heap Used:", process.memoryUsage().heapUsed / 1024 / 1024, "MB");
console.log("RSS:", process.memoryUsage().rss / 1024 / 1024, "MB");
If the rss value in process.memoryUsage() closely matches the value in pm2 monit while heapUsed is significantly lower, the restart is being triggered by non-heap memory growth.
Diagnostic Note: Are you using any native C++ addons or processing large binary files via Buffers? If so, the RSS trigger is likely reacting to those specific allocations.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 28 Apr 2022, 06:48 UTC
While it is established that PM2 monitors the Resident Set Size (RSS), it is important to note that RSS can remain high even after the V8 garbage collector has reclaimed heap memory. This is due to memory fragmentation and the way the system allocator (glibc or jemalloc) manages memory pages.
In scenarios where an application frequently allocates and deallocates large buffers, the OS may not immediately reclaim those pages, causing the RSS to stay above the max_memory_restart threshold despite a low heapUsed value. To verify if fragmentation is triggering premature restarts, you can monitor the difference between these metrics:
process.memoryUsage().heapUsed (Actual objects in V8)process.memoryUsage().rss (Total memory allocated by the OS)If the gap between these two grows consistently, the restarts are likely caused by the allocator's inability to return memory to the OS rather than a traditional application-level leak.