How to preserve the data of a chart node across a restart of Node Red?

I visualize in a Chart Node the data of a climate sensor over a longer period of time.
Unfortunately, every time Node Red is restarted, all data recorded up to that point is lost.
Has anyone already solved this problem and can give me a corresponding example flow?
Many thanks in advance!
Harald

The obvious answer is to use a database.

I do this with Mariadb and the basic Node-red dashboard charts.

Many others use influxdb and grafana to draw the graphs.

If you search the forum you should find many examples.

A simple way to persist the graph info is to use the node-red-contrib-persist nodes.

The output of the chart node is connected to the input of the ‘persist in’ node.

The ‘persist out’ node connects to the input of the chart node.
(Along with whatever feeds data to your chart)

Before shutdown, the data will be saved to a file.

or you could use the cache node from uibuilder along with a persistent context store.

Many thanks, this is what I was looking for.

Unfortunately, however, I have now destroyed my Node Red installation: Since the file was not saved in the desired folder, I deleted the configuration of the file and performed a deploy. Now Node Red does not start anymore, because the persistence nodes produce an uncaught exception:

1 Aug 15:25:36 - [red] Uncaught Exception:
1 Aug 15:25:36 - [error] TypeError: Cannot read properties of null (reading 'getMessage')
    at EventEmitter.PersistOutNode.node.restore (/root/.node-red/node_modules/node-red-contrib-persist/persist.js:159:40)
    at EventEmitter.emit (node:events:539:35)
    at Object.start [as startFlows] (/usr/lib/node_modules/node-red/node_modules/@node-red/runtime/lib/flows/index.js:407:12)
nodered.service: Main process exited, code=exited, status=1/FAILURE
nodered.service: Failed with result 'exit-code'.

Do you have any idea how I can get my installation working again?

I have found it: node-red --safe

This flow shows you to save and restore a chart.
https://flows.nodered.org/flow/92920b4fd450bf92a3035e061947daa0

Many thanks. I think I will build on this example as the persistence nodes also throw some other warnings (use of deprecated function).

I have now designed a subflow that solves the problem using SQLite:

Example flow:

[{"id":"0cb6bf1c544ebd85","type":"subflow","name":"Chart Persistence","info":"","category":"","in":[{"x":60,"y":80,"wires":[{"id":"ef3ff83b.aa5008"}]}],"out":[{"x":840,"y":280,"wires":[{"id":"4f8411277831e52e","port":0}]}],"env":[{"name":"Node","type":"str","value":""}],"meta":{},"color":"#DDAA99","status":{"x":840,"y":80,"wires":[{"id":"fa4020ebfee2ed9a","port":0}]}},{"id":"ef3ff83b.aa5008","type":"json","z":"0cb6bf1c544ebd85","name":"","x":170,"y":80,"wires":[["26de10021a1548a7"]]},{"id":"7a999f0bb3f4d802","type":"sqlite","z":"0cb6bf1c544ebd85","mydb":"d98f5a8b0d088b01","sqlquery":"prepared","sql":"INSERT OR REPLACE INTO Node_Data VALUES($Node,$Data)","name":"Write","x":510,"y":80,"wires":[["fa4020ebfee2ed9a"]]},{"id":"26de10021a1548a7","type":"function","z":"0cb6bf1c544ebd85","name":"Set msg.params","func":"if (flow.get(\"initialized\") === true) {\n    msg.params = { \n        \"$Node\": env.get(\"Node\"),\n        \"$Data\": msg.payload \n    }\n    return msg;\n}\nelse\n    return null;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":80,"wires":[["7a999f0bb3f4d802"]]},{"id":"4f8411277831e52e","type":"json","z":"0cb6bf1c544ebd85","name":"","x":730,"y":280,"wires":[[]]},{"id":"6c4202929fcc9b69","type":"sqlite","z":"0cb6bf1c544ebd85","mydb":"d98f5a8b0d088b01","sqlquery":"prepared","sql":"SELECT DATA FROM Node_Data WHERE(NODE=$Node)","name":"Read","x":510,"y":220,"wires":[["cf17623e6f0e211b"]]},{"id":"cf17623e6f0e211b","type":"change","z":"0cb6bf1c544ebd85","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[0].DATA","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":220,"wires":[["4f8411277831e52e"]]},{"id":"037ab12c9bca1d22","type":"function","z":"0cb6bf1c544ebd85","name":"Set msg.params","func":"msg.params = { \n    \"$Node\": env.get(\"Node\")\n}\nflow.set(\"initialized\",true)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":220,"wires":[["6c4202929fcc9b69"]]},{"id":"fd11c6e044c9d6ce","type":"sqlite","z":"0cb6bf1c544ebd85","mydb":"d98f5a8b0d088b01","sqlquery":"fixed","sql":"CREATE TABLE IF NOT EXISTS Node_Data(NODE TEXT PRIMARY KEY NOT NULL,DATA TEXT NOT NULL)","name":"Create Table","x":330,"y":160,"wires":[["037ab12c9bca1d22"]]},{"id":"fa4020ebfee2ed9a","type":"function","z":"0cb6bf1c544ebd85","name":"Status \"dot\"","func":"msg.payload = {fill:\"green\",shape:\"dot\",text:env.get(\"Node\")}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":670,"y":80,"wires":[[]]},{"id":"bd3b56346aacbcf1","type":"inject","z":"0cb6bf1c544ebd85","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"0.1","topic":"","payload":"true","payloadType":"bool","x":170,"y":160,"wires":[["fd11c6e044c9d6ce"]]},{"id":"d98f5a8b0d088b01","type":"sqlitedb","db":"/home/node-red/persistence.sql","mode":"RWC"},{"id":"0b6404af633acaac","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"cd9313eba6a1ec1a","type":"subflow:0cb6bf1c544ebd85","z":"0b6404af633acaac","name":"Chart Persistence Demo","env":[{"name":"Node","value":"Chart Persistence Demo","type":"str"}],"x":630,"y":120,"wires":[["7e36c3ccf9ce0072"]]},{"id":"b045f9e321fcc5b3","type":"inject","z":"0b6404af633acaac","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":true,"onceDelay":0.1,"topic":"random","payload":"true","payloadType":"bool","x":110,"y":120,"wires":[["a50c50c540272816"]]},{"id":"7e36c3ccf9ce0072","type":"ui_chart","z":"0b6404af633acaac","name":"","group":"884daaba08bae0a4","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":430,"y":120,"wires":[["cd9313eba6a1ec1a"]]},{"id":"a50c50c540272816","type":"function","z":"0b6404af633acaac","name":"Random","func":"msg.payload = Math.random()\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":280,"y":120,"wires":[["7e36c3ccf9ce0072"]]},{"id":"884daaba08bae0a4","type":"ui_group","name":"Chart Persistence Demo","tab":"5dd649e34ebbd68e","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"5dd649e34ebbd68e","type":"ui_tab","name":"Persistence Demo","icon":"dashboard","disabled":false,"hidden":false}]