Node-RED Global Context and Node.js Heap Memory Integration
0 reputation · 20 Jul 2023, 11:06 UTC
0 reputation · 20 Jul 2023, 11:06 UTC
Node-RED utilizes the Node.js runtime, where the global context API provides a mechanism for sharing data across different flows. By default, this context is stored in memory, meaning any objects or arrays assigned to the global scope reside directly on the Node.js heap.
While the runtime handles standard garbage collection, there is a known architectural gap regarding the isolation of memory consumption. Specifically, there is no native, declarative method to set a memory quota or limit for a specific flow or individual function node. This creates a risk where a single flow utilizing the memory-based global store can exhaust the entire process heap, leading to Out-of-Memory (OOM) crashes for the entire Node-RED instance.
Given the current implementation of the Context Storage API in recent versions, what are the best practices for preventing a single flow from impacting the global heap? Is there a way to implement per-flow memory constraints without migrating the entire global store to a file-based or database-backed persistence layer?
32275 reputation · 20 Jul 2023, 11:16 UTC
The safest way to keep a single flow from draining the Node.js heap while still using the default in‑memory context store is to bound the data you place in global context and to monitor heap usage so you can act before the limit is reached.
global.get/set directly into the V8 heap, so its size contributes to process.memoryUsage().heapUsed.Storing large JSON objects, arrays, or Buffers in global context increases heap consumption proportionally. If a single flow repeatedly adds data without removing stale entries, heap usage will grow until garbage collection can no longer keep up, leading to longer GC pauses or an OOM crash that affects the entire Node‑RED instance.
global.set(key, value), check an approximate size (e.g., JSON string length or Buffer.byteLength) and refuse or truncate if it exceeds a per‑flow threshold.process.memoryUsage() via a debug node or the Node‑RED admin API (GET /context/global when using the memory store) and set an alert when heapUsed approaches, say, 80 % of the configured --max-old-space-size.--max-old-space-size (e.g., 512 MB) so that any runaway growth triggers an OOM early, making the problem visible during testing rather than in production.# 1. Record baseline heap node -e "console.log(process.memoryUsage().heapUsed)" # 2. Inject a 10 MB JSON object into global context via a function node # 3. Record heap again and confirm the increase (~10 MB) # 4. Reduce heap limit and test OOM: node --max-old-space-size=100 red.js # 5. Observe the fatal error when stored data exceeds the limit.If you need to know the exact size of a particular global key to tune your limits, ask for that measurement; otherwise the steps above apply.
Use comments to ask for clarification. Post a solution as an answer.
32,275 reputation · 20 Jul 2023, 19:17 UTC
Node‑RED’s Context Storage API now lets you assign a different store to a single flow. By adding a contextStorage key in the flow file you can plug in a lightweight LRU cache that lives entirely in memory.
{
"id": "flow1",
"type": "tab",
"label": "Example Flow",
"contextStorage": "lruStore"
}
Implement lruStore as a custom store that tracks key count and evicts the oldest entry when a threshold (e.g., 100 keys) is exceeded. This keeps the flow’s data isolated from the global heap.
Expose the Node‑RED metrics endpoint (/api/metrics) to monitor context.lruStore.size and process.memoryUsage().heapUsed. Trigger cleanup routines when the store approaches its limit.
Optionally set Node.js’s --max-old-space-size to a conservative value to provide a safety net for the entire process.