Configuring File-Based Context Persistence in Node-RED
Learn how to configure Node-RED's file-based context storage so flow and global variables survive restarts. Includes a ready-to-use settings.js snippet, serialization rules, common pitfalls, and verification steps.
23 Mar 2026, 04:35 UTC

Why context disappears on restart
Node-RED's default context store keeps flow and global variables in memory. When the runtime restarts — whether from a deploy, a crash, or a container restart — that state is lost. For any production flow that relies on counters, cached tokens, or last-seen timestamps, you need a persistent store.
How context storage works
Node-RED provides three context scopes:
- Node context – private to a single node instance, never persisted.
- Flow context – shared across all nodes on the same editor tab (flow).
- Global context – shared across every flow in the runtime.
Each scope can be backed by a pluggable store module. The built-in memory store is the default; localfilesystem writes JSON files to disk, and redis enables horizontal scaling.
Worked configuration: file-based persistence
Edit settings.js (typically in ~/.node-red/ or /data/settings.js in Docker) and add a contextStorage object. The snippet below persists both flow and global context, flushing every 30 seconds:
contextStorage: {
default: {
module: "localfilesystem"
},
flow: {
module: "localfilesystem"
},
global: {
module: "localfilesystem",
options: {
flushInterval: "30s"
}
}
}
With this configuration:
- Flow context writes to
<userDir>/context/flow.json. - Global context writes to
<userDir>/context/global.json. - The
flushIntervalaccepts human-readable strings (e.g., "30s", "5m") in Node-RED 3.1+; older versions require milliseconds as an integer. - Writes are atomic: the store writes to a temporary file then renames, so a power loss won't corrupt the JSON.
What you can store — and what you can't
Only JSON-serializable values survive a flush. Functions, Date objects, Buffers, and circular references are either dropped or cause serialization errors. Convert dates to ISO strings (new Date().toISOString()) or numeric timestamps before calling context.set().
Common mistakes and limits
Manual file edits while Node-RED runs
The runtime caches context in memory and overwrites the file on the next flush. Stop Node-RED, edit the file, then restart — or use the admin API (POST /context/global/:key) to update safely.
Container deployments without persistent volumes
In Kubernetes or Docker Compose, the <userDir>/context directory must be backed by a PersistentVolume or a bind mount. Otherwise a pod restart recreates an empty context directory.
Sharing a context directory across instances
The localfilesystem store is single-process. Running multiple Node-RED instances against the same directory causes write conflicts. Use the Redis store for horizontal scaling.
Large global objects
Objects larger than a few megabytes increase flush latency and memory pressure. Offload bulky data to an external database and keep only references (IDs, keys) in context.
Flush interval too aggressive
Setting flushInterval: 0 forces a synchronous write on every context.set(). Under high write frequency this blocks the event loop and degrades throughput. The default 30-second interval is a good starting point; tune based on I/O monitoring.
Encryption at rest
The file store does not encrypt data. Rely on full-disk encryption (LUKS, BitLocker, cloud provider encryption) or implement a custom store module if you need application-level encryption.
Context visibility within a single message pass
Changes made by context.set() inside a Function node are not visible to downstream nodes in the same message execution because those nodes already captured the old snapshot. The updated value appears on the next incoming message.
Verification checklist
- Validate syntax: Run
node -c /path/to/settings.js— it must exit without errors. - Check active store: With
adminAuthenabled, callGET /context/via the admin API; the response lists the store type and keys for each scope. - Test persistence: Inject a timestamp into global context (e.g.,
global.set("test", Date.now())), restart Node-RED (systemctl restart noderedordocker restart), then verify the value survives using a debug node or the admin API. - Monitor flush I/O (optional):
strace -e trace=write -p <pid> | grep contextconfirms writes occur at the configured interval.
Summary
File-based context persistence is a few lines in settings.js and a persistent volume. It survives restarts, keeps flow and global state separate, and uses atomic writes. Remember the serialization limits, avoid manual file edits, and size your flush interval to your workload. For multi-instance deployments, switch to the Redis store.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.