Persisting State in Node-RED Using the Local Filesystem Context Store
Learn how to use the localfilesystem context store in Node-RED to ensure your flow and global variables survive restarts and deploys.
16 Apr 2026, 05:53 UTC

Solving the State Loss Problem
By default, Node-RED stores flow and global context in volatile memory. Every time you deploy a flow, restart the Node-RED service, or reboot the host, stored variables—counters, last-seen timestamps, device states—are wiped. To keep state across restarts without deploying a full database, configure a persistent context store in settings.js.
The most direct solution for small, slowly-changing state is the localfilesystem store. This module mirrors context values to JSON files on disk, and the runtime reloads them at startup.
Configuring the Persistent Store
Enable persistence by adding a contextStorage object to your settings.js file (typically ~/.node-red/settings.js). You can define multiple named stores and choose which one is the default.
// settings.js
contextStorage: {
default: 'memory',
memory: {
module: 'memory'
},
file: {
module: 'localfilesystem'
}
}Here, memory stays the default for fast, volatile operations, while the file store is available for data that must survive a reboot. Save the file and restart the Node-RED process for the change to take effect. Check the startup log for context store initialization messages to confirm both stores loaded without errors.
Implementing Persistent Logic in Function Nodes
When calling flow.set() or global.set(), explicitly pass the store name as an argument. If you omit it, Node-RED silently uses the default store—this is the single most common cause of "persistence not working."
Example: a counter that tracks total messages processed across restarts. In a Function node:
// Retrieve the current count from the 'file' store.
// If it doesn't exist yet, default to 0.
let count = flow.get('totalMessages', 'file') || 0;
// Increment the value
count++;
// Save the updated value back to the 'file' store
flow.set('totalMessages', 'file', count);
msg.payload = "Total messages processed: " + count;
return msg;How to verify it works:
- Deploy the flow and trigger the node several times.
- Restart the Node-RED service.
- Trigger the node again; the count should resume from the last value instead of resetting to 1.
- Inspect the
contextdirectory under your userDir (e.g.,~/.node-red/context) and confirm JSON files exist containing your flow and global keys.
Limitations and Engineering Trade-offs
The localfilesystem store is a convenience feature, not a database replacement. Knowing its limits prevents data loss and performance problems.
Data Type Constraints
Because the store writes JSON files, only JSON-serializable values persist correctly. The following will be lost or corrupted:
- JavaScript functions
- Buffers
- Circular references (objects that refer to themselves)
- Complex class instances
Write Frequency and Crash Window
The localfilesystem module caches values in memory and flushes to disk periodically (roughly every 30 seconds by default). A sudden power failure or hard crash can lose any writes made within that window. Do not use it for state where losing the last half-minute of data is unacceptable.
Scope Restrictions
Persistence is only available for flow and global scopes. Node-scoped context is always volatile and cannot be backed by the filesystem store.
Not for High-Frequency or Large Data
Persistent context suits small, slowly-changing state: counters, last-seen timestamps, configuration flags. High-frequency writes or large payloads perform poorly and risk file corruption—use SQLite, InfluxDB, or another real database for time-series or bulk data.
Common Implementation Mistakes
| Mistake | Result | Correction |
|---|---|---|
Omitting the store name in .get() or .set() | Data goes to the default (memory) store and is lost on restart | Always pass 'file' as the store argument |
| Using the file store for high-frequency logging | Disk I/O overhead and potential file corruption | Use a proper database for time-series data |
| Changing the default store after flows exist | Previously persisted values become orphaned under the old store name | Keep store names consistent or migrate the JSON files manually |
| Storing non-serializable objects | Values reload as empty objects or are dropped | Convert to plain JSON-safe structures before saving |
Note that exact setting names and default flush intervals are version-sensitive; confirm them against the settings.js template shipped with your installed Node-RED version.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.