Node-RED Context Stores: Pick Memory, File, or Redis for Your Flow State
How to choose between Node-RED's memory, file, and Redis context stores, with a settings.js example and restart persistence test.
17 Jul 2025, 14:14 UTC

The problem: state disappears when Node-RED restarts
You wire a Function node to increment a counter every time a sensor message arrives. The dashboard shows the right number until you redeploy or reboot. After restart, the counter is zero again. If you run two Node-RED instances behind a load balancer, each instance keeps its own counter, so the dashboard flickers depending on which instance handles the request.
Node-RED keeps flow and global context in memory by default. That works for temporary values, but it does not survive restarts and is not shared between runtime instances. To keep state, you need to configure a context store.
How context stores work
Node-RED separates context into flow context (visible to nodes inside one flow) and global context (visible to all flows). A context store is the backend that reads and writes those key-value pairs. Each key is stored separately; in the file backend, every key becomes its own JSON file under context/flow/ or context/global/. Flow context keys are internally prefixed with the flow ID, so two flows can use the same key name without colliding.
Since Node-RED 2.0, context.get() and context.set() return promises in file and Redis stores. Older synchronous code in Function nodes will not wait for the write to finish, so you should use await or .then() when you switch away from memory.
Compare the three backends
| Store | Survives restart | Shared across instances | Best for |
|---|---|---|---|
| Memory (default) | No | No | Temporary counters, session state on one instance |
| Local filesystem | Yes | No | Single-instance persistence, easy backup |
| Redis | Yes | Yes | Multiple instances, horizontal scaling |
Memory is fastest but empty after a restart. File storage survives restarts on the same machine, but every context.set() touches disk, which can wear out SD cards on a Raspberry Pi and adds latency on high-frequency updates. Redis lets multiple Node-RED processes read and write the same state, but it adds a network round trip and requires you to run and secure a separate service.
Configure the store in settings.js
Edit your Node-RED settings file, typically settings.js in your Node-RED user directory. Add or edit the context block. Non-core stores such as Redis require the module property and the corresponding npm package installed in your Node-RED directory.
context: {
flow: {
store: 'localfilesystem'
},
global: {
store: 'redis',
module: 'node-red-contrib-context-redis',
config: {
host: '127.0.0.1',
port: 6379
}
}
}
Run this command in the directory where Node-RED is installed to add the Redis package:
npm install node-red-contrib-context-redis
Where to run: a terminal on the host running Node-RED, as the user that owns the Node-RED installation. Permissions: write access to settings.js and the Node-RED node_modules directory. Risk: a syntax error in settings.js prevents Node-RED from starting, so back up the file before editing and keep the terminal open until you confirm startup.
Worked example: persist a flow counter across restart
This example assumes Node-RED 2.0 or later. Check your version first:
node-red --version
1. In the Node-RED editor, add an Inject node connected to a Function node.
2. Paste this into the Function node:
let count = await flow.get('sensor_count') || 0;
count += 1;
await flow.set('sensor_count', count);
return { payload: count };
3. Deploy the flow, click the Inject node, and note the number.
4. Restart Node-RED (for example, restart the service or container).
5. Click the Inject node again. If the file or Redis store is configured correctly, the number continues from where it left off. With the default memory store, it resets to 1.
Expected check: look at the Node-RED startup log for a line indicating which context store initialized. If you do not see one, or the Function node throws an error about await, your Node-RED version may predate the async context API.
Risk: writing to context on every message can create many small file writes. For high-frequency sensors, batch the value in a flow variable and write to context once per minute instead of on every message.
Limitations and what to verify
- File and memory stores have no built-in TTL. Expired keys must be cleaned up by your flow.
- File store is not shared across instances. Two Node-RED processes writing to the same context directory can overwrite each other.
- Redis is community-maintained (
node-red-contrib-context-redis), not part of Node-RED core. Verify compatibility with your Node-RED version before production use. - There is no built-in migration tool between stores. Moving from memory to file or Redis requires exporting keys and writing them to the new backend, typically with a custom script.
- Do not store API keys or passwords in context. Use environment variables or Node-RED's credential store instead.
Practical verification before you deploy
- Run
node-red --versionand confirm you are on 2.0+ if you plan to useawaitin Function nodes. - Inspect
settings.jsfor thecontextblock and confirm any referenced module appears innpm list. - Deploy the counter flow above, restart Node-RED, and confirm the value persists.
- Check startup logs for context-store initialization messages.
- If you use Redis, confirm authentication and TLS are enabled in production; do not expose Redis to the public internet.
Closing
Start with memory if your state is temporary and single-instance. Switch to file storage when you need values to survive a restart on one machine. Choose Redis only when multiple Node-RED instances must share state, and treat it as an operational dependency you must back up, secure, and monitor like any other database.
After changing settings.js, restart Node-RED and run the counter test above before trusting the flow with production data.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.