# A guide to understanding 'Persistent Context'

**URL:** https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115
**Category:** General
**Created:** [19 October 2018 10:13 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115 "2018-10-19T10:13:24Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)
#### Post date: [19 October 2018 10:13 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/1 "2018-10-19T10:13:24Z")

</div>

This is something I wrote up after playing with the context options. I've filed a PR with some of this added to the Node-RED documentation but thought I'd release it here also. I hope people find it useful.  
Paul

* * *

**A guide to understanding 'Persistent Context'**

Prior to Node-RED v0.19.0, data could be stored in context as a global, flow or node. This was stored in memory and would be reset with a restart of Node-RED. As of v.0.19.0 you can now store node, flow and global context data in memory OR in a file which will persist over restarts. (the data will be stored in the userDir, which is normally $HOME/.node-red, in a folder 'context' with subfolders for each flow or node and one folder for all globals.)

In order to store the data, you must make a change to `settings.js` - without the change, context stores will always be in memory and will not be persistent.

The contextStorage property in settings.js is used to configure how context data is stored:

```auto
    contextStorage: {
    	storeName : { module: "storeModule" }
    },

```

`storeName`: The storeName used in get/sets  
  
`storeModule`: Node-RED provides two built-in store modules: `memory` and `localfilesystem`. It is also possible to create custom store plugins. You must specify localfilesystem (or your own custom module) to make the data persistent. For details on creating custom modules, see the api pages.

If you only have one option in contextStorage, it will always be used. If you have two options and one has the storeName `default` (order doesn't matter) it will be used if the get/set storeName option is not used. If you try to `get` or `set` using a location storeName that does not exist, it will use the default and you will see a one time warning in the log.

Example: say these are your entries in setting.js:

```auto
    contextStorage: {
		storeInFile: { module: "localfilesystem"},
    	default : { module: "memory" }
    },

```

And you use the following set's (this applies to any node that can access context directly like the change, inject, or change nodes):

```auto
flow.set("count", 123); // stored in memory, count = 123
flow.set("count", 234, "default"); // stored in memory, count now - 234
flow.set("partid", "b301", "storeInFile"); // stored in file, partid = "b301"
flow.set("color", "red", "InFile"); // invalid storeName 
                                      // - stored based on 'default' rules
                                      // - a 'storeName' of `default` exists and is used
                                      // - stored in memory, color = 'red'

```

Note: Having multiple entries in settings.js can lead to confusion. If you have:

```auto
    contextStorage: {
    	default : { module: "memory" },
		storeInFile: { module: "localfilesystem"},
		memoryOnly : { module: "memory" }
    },

```

and run the following code:

```auto
	flow.set("count", 123); // the value is stored in memory
	flow.set("count", 234, "default"); // the value is stored in memory
	flow.set("count", 345, "memoryOnly"); // the value is stored in memory

```

the first line stores '123' in default:count.  
the second line replaces '123' with '234' in default:count  
the third line stores '345' in memoryOnly:count

If you forget to specify the location in a `get` or `set`, you might end up with the wrong value.

**SUGGESTION:** If you want have all your context data be persistant, setup your settings.js file with the following:

```auto
    contextStorage: {
    	default : { module: "localfilesystem"}
    },

```

## Here are some more examples

**Example 1:** default to memory, require a name for storing in a file

```auto
    contextStorage: {
    	default : { module: "memory" },
		storeInFile: { module: "localfilesystem"}
    },

```

```auto
	flow.set("count", 123); // the value is stored in memory
	flow.set("count", 234, "default"); // the value is stored in memory
	flow.set("ID", 345, "storeInFile"); // the value is stored in a file
	flow.set("date", 345, "somewhere"); // since there is no storeName "somewhere", 
	                                     // and there is a storeName "default",
	                                     // the value is stored in memory

```

**Example 2:** default to persistant require a name for storing in memory

```auto
    contextStorage: {
		storeInFile: { module: "localfilesystem"}
    	memoryOnly : { module: "memory" },
    },

```

```auto
	flow.set("total", 123); // since no option is provided and there is no "default"
							 // option, the first option "storeInFile" is used so
							 // the value is persistant and stored in a file
	
	flow.set("count", 234, "memoryOnly"); // the value is stored in memory
	flow.set("ID", 345, "storeInFile"); // the value is stored in a file
	flow.set("date", 345, "somewhere"); // since there is no storeName "somewhere" and 
	                                      // there no storeName "default" the first 
	                                      // storeName is used ('storeInFile') so the 
	                                      // value is persistant and stored in a file

```

---

<div class="post-metadata">

### Author: ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)
#### Post date: [19 October 2018 10:43 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/2 "2018-10-19T10:43:03Z")

</div>

Nice work ! but is below correct ? - or is the comment wrong ? or...

> [@zenofmud](#):
>
> flow.set("count", 345, "memoryOnly"); // the value is stored in a file

---

<div class="post-metadata">

### Author: ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)
#### Post date: [19 October 2018 11:45 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/3 "2018-10-19T11:45:10Z")

</div>

Oops 😱 the comment was wrong (corrected) - this is why everyone needs an editor 😁

---

<div class="post-metadata">

### Author: ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)
#### Post date: [19 October 2018 14:45 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/4 "2018-10-19T14:45:19Z")

</div>

Just one little thought about persistent context & writing...to sd cards

Does this new elegant feature increase the wear on the sd card? I can see that files are being updated rather frequently. We learned we should write as few times as possible, turned off disk write access as much as possible. I'm currently using MQTT with retain flag saving all statuses in an object to be able to recover at init. A second thought, most likely MQTT writes to disk anyway when you use the retain flag

What is your opinion on this? Maybe OT but still related...

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [19 October 2018 15:10 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/5 "2018-10-19T15:10:13Z")

</div>

@krambriw _any_ sort of persistent storage needs to write to the SD card, unless you use some external storage mechanism (USB hard drive, cloud storage api...). It's hard to get around that.

To help minimise the wear, the default mode for the file persistence is to batch up writes to the card every 30 seconds. This does mean if Node-RED crashes unexpectedly, you may not have up to the last 30 seconds worth of data stored. That's the trade-off between writing every update to disk as it happens and trying to minimise wear.

---

<div class="post-metadata">

### Author: ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)
#### Post date: [19 October 2018 15:28 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/6 "2018-10-19T15:28:55Z")

</div>

I would not worry too much about writing small amounts of data to the card. Provided you use good quality cards it should not be an issue unless you are repeatedly writing megabytes of data.  
Even the lowest spec cards quote thousands of write cycles, which means writing the whole card several thousand times. If you want a life of, say, 10 years that is 3650 days (give or take a couple of leap days) so you could rewrite the whole card (maybe 8GB) every day and still expect it survive many years. In practice it is not that simple but it gives a feel for the figures.

---

<div class="post-metadata">

### Author: ![tilleul](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/tilleul/32/78_2.png) [@tilleul](https://discourse.nodered.org/u/tilleul)
#### Post date: [19 October 2018 17:08 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/7 "2018-10-19T17:08:44Z")

</div>

Also, it's certainly possible to write persistent context to a non-wearable media like a network hard drive or something ?

---

<div class="post-metadata">

### Author: ![StrongTown](https://avatars.discourse-cdn.com/v4/letter/s/4bbf92/32.png) [@StrongTown](https://discourse.nodered.org/u/StrongTown)
#### Post date: [19 October 2018 19:01 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/8 "2018-10-19T19:01:25Z")

</div>

Great write up. I have one question however. When I wish to check on the stored value (file store) the directories under 'context' use obscure node numbering. Would it be possible to use the tab name, (or node name) which is what one might expect to look under? Just a thought. I only care when I'm coding because that's when I'm checking to see things are doing what I expected. But I have to say, I do love the persistent context. Have done a lot of rewriting to incorporate it but the previous solutions I created were not 1,000% reliable and certainly not as elegant as this.  
ST

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [19 October 2018 19:03 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/9 "2018-10-19T19:03:49Z")

</div>

> [@StrongTown](#):
>
> Would it be possible to use the tab name, (or node name) which is what one might expect to look under?

The file store isn't really intended for the user to access directly - its an internal implementation detail. The naming is based on the id of the nodes and flows as they are guaranteed to be unique and don't change. Node names can be changed by the user and you can have many nodes named the same thing.

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [19 October 2018 19:04 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/10 "2018-10-19T19:04:28Z")

</div>

> [@tilleul](#):
>
> Also, it's certainly possible to write persistent context to a non-wearable media like a network hard drive or something ?

yes, that's what I meant in my reply where I said:

> use some external storage mechanism (USB hard drive, cloud storage api...).

---

<div class="post-metadata">

### Author: ![StrongTown](https://avatars.discourse-cdn.com/v4/letter/s/4bbf92/32.png) [@StrongTown](https://discourse.nodered.org/u/StrongTown)
#### Post date: [19 October 2018 19:22 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/11 "2018-10-19T19:22:04Z")

</div>

OK, I understand. Thank you.

BTW, I think I read it's not on the list for development however, just for some feedback, I would vote in support of being able to create a utility function somewhere that I can globally call upon in any flow / node rather than repeat code in many function nodes. (NOTE: creating a custom / private NR node for this would be overkill and I think less elegant). I have succeeded in achieving this by assigning a function to a context.global variable (NR complains when it starts) but I read this is not recommended and that it may be policed one day. I took it out when I read that because I didn't want to have to go back deep into all my code at some future date when I forgot all the tiny little details should the ability to do this change. Just so you know .... some input from the cheap seats.

---

<div class="post-metadata">

### Author: ![RogierQ](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogierq/32/3211_2.png) [@RogierQ](https://discourse.nodered.org/u/RogierQ)
#### Post date: [19 October 2018 21:00 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/13 "2018-10-19T21:00:51Z")

</div>

Cool!

But were do i place this?

```
contextStorage: 
	storeName : { module: "storeModule" }
}

```

When i put it in the end before the last } i get an error on starting node-red.

Do i understand well that when i put this in settings.js that the global are persistent?

---

<div class="post-metadata">

### Author: ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)
#### Post date: [19 October 2018 21:05 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/14 "2018-10-19T21:05:49Z")

</div>

It’s not that it will be policed. Most storage mechanisms only really support serialisable objects, and functions aren’t serialisable. So now we do have persistable context, depending on the storage mechanism, functions (and circular objects) won’t be stored.

---

<div class="post-metadata">

### Author: ![RogierQ](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogierq/32/3211_2.png) [@RogierQ](https://discourse.nodered.org/u/RogierQ)
#### Post date: [19 October 2018 21:12 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/15 "2018-10-19T21:12:36Z")

</div>

> [@zenofmud](#):
>
> contextStorage: storeInFile: { module: "localfilesystem"}, default : { module: "memory" } },

Solved! There was an { missing after contextStorage:

---

<div class="post-metadata">

### Author: ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)
#### Post date: [19 October 2018 21:15 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/16 "2018-10-19T21:15:33Z")

</div>

'storeName' and 'storeModule' are the place holder names. Did you look at the examples?

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [19 October 2018 21:20 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/17 "2018-10-19T21:20:52Z")

</div>

As @zenofmud mentions, he's raised a pull-request to get this integrated into our proper documentation - I'm keen we have good docs that can be linked to for these sorts of questions, rather than rely on linking to forum posts.

The pull-request is here: [https://github.com/node-red/node-red.github.io/pull/86](https://github.com/node-red/node-red.github.io/pull/86)

Please take a look at the proposed changes and provide any feedback on the PR - and also marvel at how easy it is to contribute to the documentation... 😉

---

<div class="post-metadata">

### Author: ![RogierQ](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogierq/32/3211_2.png) [@RogierQ](https://discourse.nodered.org/u/RogierQ)
#### Post date: [19 October 2018 21:34 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/18 "2018-10-19T21:34:08Z")

</div>

agree, but i really dont understand how to do that, but instead of doing nothing i post it here in the hope it helps some one...

It's all ready difficult enough for me to get it working 😉  
Because when i stop start NR now the global.get is still empty

---

<div class="post-metadata">

### Author: ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)
#### Post date: [19 October 2018 21:52 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/19 "2018-10-19T21:52:11Z")

</div>

@RogierQ - your right, the opening '{' was missing - fixed now.

---

<div class="post-metadata">

### Author: ![RogierQ](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rogierq/32/3211_2.png) [@RogierQ](https://discourse.nodered.org/u/RogierQ)
#### Post date: [20 October 2018 06:42 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/20 "2018-10-20T06:42:56Z")

</div>

What is not clear to me now, is when it is saved

Doing some tests the results of saved global dont show up directly in the json file  
Or is it saved when deploying?

@zenofmud thanks!

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [20 October 2018 07:08 UTC](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115/21 "2018-10-20T07:08:51Z")

</div>

It may help if you share exactly what you have put in your settings file and show us how you then set a value in context - just so we can check you're doing it right.

[Next page](https://discourse.nodered.org/t/a-guide-to-understanding-persistent-context/4115.md?page=2)
