# Backing up context data

**URL:** <https://discourse.nodered.org/t/backing-up-context-data/82260>\
**Category:** General\
**Tags:** docker\
**Created:** [22 October 2023 18:55 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260 "2023-10-22T18:55:54Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hunter](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hunter/32/60045_2.png) [@Hunter](https://discourse.nodered.org/u/Hunter)\
**Post date:** [22 October 2023 18:55 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/1 "2023-10-22T18:55:54Z")

</div>

Hi all,

About 2 years ago, I posted the same issue;

> [@Backing up data](https://discourse.nodered.org/t/backing-up-data/54368):
>
> Hello, I'n using NR to provide data to a large group of users (it was \> 1000 but after I lost my data I'm back about 300 now). Each user has it's own settings, stored in aUsers object, stored als file : flow.set("aUsers", aUsers, "storeInFile"); Just to be sure, if I mess up anything, I created a change node which is injected once every day to backup my data. If necessary, I would be able to access a backed up copy of the user settings. So far, so good, the data gets copied into aUsersBackup …

Still, I'm facing the same issue and I'm wondering if there are any new thoughts on this?

Let me summarize my issue. My NodeRED feeds a Telegram system with about 3000 users. The user-data is stored in object as

`flow.set("aUsers", aUsers, "storeInFile");`

Once a day I would like to make a backup. In the beginning (years ago) I messed up this object once and I didn't have a backup. So I inject this every 24 hours :

`const aUsers = flow.get("aUsers", "storeInFile"); flow.set("aUsers_backup", aUsers);`

So far, so good. But the strange thing is, that this backup somehow is **allways** a live copy. Even if I stop injecting the backup code, the backup allways contains the same data. And, there comes the tricky part... If I delete my aUsers, the aUsers\_backup also gets lost...?

I'm running NR in docker on NGINX.

Any suggestions maybe?

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [22 October 2023 19:19 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/2 "2023-10-22T19:19:37Z")

</div>

Hi @Hunter,

Admittedly, I have not read the original thread.

But my hunch here, is referencing...

Javascript (like most) will `pass-by-ref` for objects/classes, whereas for primitive types, they are  
`pass-by-value`

So what may be happening here, is your backup is a reference to the original (and not a copy)  
so when the original changes, so does any 'reference' to it.

Try using `RED.util.cloneMessage()` to see if it makes a difference

```auto
const aUsers = flow.get("aUsers", "storeInFile");
flow.set("aUsers_backup", RED.util.cloneMessage(aUsers));

```

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [22 October 2023 19:26 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/3 "2023-10-22T19:26:44Z")

</div>

And the real issue is that your backup is not using the `storeInFile` type so it is only an in-memory copy which is, as stated, merely a link to the original data, not a copy.

* * *

Ideally, if you can take your Node-RED instance offline for a backup, that would ensure that the `storeInFile` context store was always in a valid state for the backup. Remembering that, by default, I think Node-RED only writes a file store to disk every 30 seconds.

I think that, if you really want a more robust store, it would be better to have a timed flow that manually writes the current context state to a file. Or even write a copy of inputs to a DB and restore from DB on startup. Database engines will have more robust backup processes.

---

<div class="post-metadata">

**Author:** ![Hunter](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hunter/32/60045_2.png) [@Hunter](https://discourse.nodered.org/u/Hunter)\
**Post date:** [22 October 2023 19:48 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/4 "2023-10-22T19:48:01Z")

</div>

> [@marcus-j-davies](#):
>
> RED.util.cloneMessage()

Thanks for the tip mate, but this seems to be using some kind of reference as well ☹

---

<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:** [22 October 2023 20:55 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/5 "2023-10-22T20:55:55Z")

</div>

> [@Hunter](#):
>
> but this seems to be using some kind of reference as well

Show us what the code now is.

---

<div class="post-metadata">

**Author:** ![kuema](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kuema/32/6542_2.png) [@kuema](https://discourse.nodered.org/u/kuema)\
**Post date:** [23 October 2023 06:32 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/6 "2023-10-23T06:32:34Z")

</div>

For such a use case, I'd go with a local SQLite database instead of using the file context. It is much more resilient regarding corruption, easy to integrate and to take backups. 🤔

---

<div class="post-metadata">

**Author:** ![Hunter](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hunter/32/60045_2.png) [@Hunter](https://discourse.nodered.org/u/Hunter)\
**Post date:** [23 October 2023 07:31 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/7 "2023-10-23T07:31:06Z")

</div>

As stated.

At several points I save the user data as;

`flow.set("aUsers", aUsers, "storeInFile");`

As for the backup, I've tried 2 options;

#1  
`const aUsers = flow.get("aUsers", "storeInFile");`  
`flow.set("aUsers_backup", aUsers);`

#2  
`const aUsers = flow.get("aUsers", "storeInFile");`  
`flow.set("aUsers_backup", RED.util.cloneMessage(aUsers));`

Both ending up in the same behaviour as described.

---

<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:** [23 October 2023 08:41 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/8 "2023-10-23T08:41:16Z")

</div>

> [@Hunter](#):
>
> `const aUsers = flow.get("aUsers", "storeInFile");`  
> `flow.set("aUsers_backup", RED.util.cloneMessage(aUsers));`

That should work. Can you post a small example flow showing it failing?

---

<div class="post-metadata">

**Author:** ![Hunter](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hunter/32/60045_2.png) [@Hunter](https://discourse.nodered.org/u/Hunter)\
**Post date:** [23 October 2023 08:48 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/9 "2023-10-23T08:48:32Z")

</div>

Well, it doesn't ☹

When I inject this code, the backup contains the same data, as expected. I use the node.warn() to show the number of users (size of object) which are both similar, as they should be.

When I register as new member, the main aUsers object increases by one, but when I run both Object.keys(aUsers).length and Object.keys(aUsers\_backup).length they are both increased by one. So the backup is not an independant object, but locked to the main object.

---

<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:** [23 October 2023 08:59 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/10 "2023-10-23T08:59:40Z")

</div>

[quote="Hunter, post:9, topic:82260"]  
when I run both Object.keys(aUsers).length and Object.keys(aUsers\_backup).length  
[/quote

In that case the aUsers\_backup variable you are using is not the one in created by  
`flow.set("aUsers_backup", RED.util.cloneMessage(aUsers));`

> [@Colin](#):
>
> Can you post a small example flow showing it failing?

That is what we need.

---

<div class="post-metadata">

**Author:** ![Hunter](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hunter/32/60045_2.png) [@Hunter](https://discourse.nodered.org/u/Hunter)\
**Post date:** [23 October 2023 09:16 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/11 "2023-10-23T09:16:53Z")

</div>

What do you mean by "failing"? There is no such failing message.  
In fact, nothing fails. But the result is not as requested.

As long as I don't log any actions, there are no messages to be shown. So what is it you want to see?

There was no backup object present when I started this second topic. It was created by :

`flow.set("aUsers_backup", RED.util.cloneMessage(aUsers));`

There is no other code which can create this object...

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 October 2023 09:24 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/12 "2023-10-23T09:24:17Z")

</div>

> [@Hunter](#):
>
> So what is it you want to see?

Just a small flow export reproducing the issue - of course using dummy data 🥸

---

<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:** [23 October 2023 10:06 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/13 "2023-10-23T10:06:46Z")

</div>

Something like this possibly, but exhibiting the problem.

```auto
[{"id":"be7131e3813e4c1c","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":2580,"wires":[["c5f859709b461748"]]},{"id":"c5f859709b461748","type":"function","z":"bdd7be38.d3b55","name":"create context value and backup","func":"const obj = {test: 7}\nflow.set(\"obj\", obj)\nflow.set(\"obj_backup\", RED.util.cloneMessage(obj))\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":2580,"wires":[["a4503b334101f033"]]},{"id":"a4503b334101f033","type":"function","z":"bdd7be38.d3b55","name":"Fetch and test","func":"const obj = flow.get(\"obj\")\nconst objBackup = flow.get(\"obj_backup\")\nobj.newStuff = \"new stuff\"\nreturn [{payload: obj}, {payload: objBackup}];","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":2580,"wires":[["7ed33b67ec465ce3"],["907c5650d0a2951b"]]},{"id":"7ed33b67ec465ce3","type":"debug","z":"bdd7be38.d3b55","name":"debug 103","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":2540,"wires":[]},{"id":"907c5650d0a2951b","type":"debug","z":"bdd7be38.d3b55","name":"debug 104","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":2600,"wires":[]}]

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [23 October 2023 10:13 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/14 "2023-10-23T10:13:43Z")

</div>

If your data is important, I would personally recommend a database backup. Preferably on a separate computer to avoid the inevitable file corruption. It doesn't have to be anything fancy.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 October 2023 16:32 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/15 "2023-10-23T16:32:48Z")

</div>

> [@Hunter](#):
>
> #1  
> `const aUsers = flow.get("aUsers", "storeInFile");`  
> `flow.set("aUsers_backup", aUsers);`
> 
> #2  
> `const aUsers = flow.get("aUsers", "storeInFile");`  
> `flow.set("aUsers_backup", RED.util.cloneMessage(aUsers));`
> 
> Both ending up in the same behaviour as described.

As previously stated, your flow.set is not using the file store and therefore is not a backup.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [22 December 2023 16:32 UTC](https://discourse.nodered.org/t/backing-up-context-data/82260/16 "2023-12-22T16:32:52Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
