In Node-RED werden Daten normalerweise von Node zu Node weitergereicht. Ein Sensorwert kommt rein, wird verarbeitet und anschließend zum Beispiel im Debug-Fenster ausgegeben, per MQTT verschickt oder in einer Datenbank gespeichert.
Aber was ist, wenn du dir einen Wert nur kurz merken möchtest?
Zum Beispiel:
- den letzten Sensorwert
- den letzten Schaltzustand
- einen einfachen Zähler
- den Zeitpunkt der letzten Aktion
- einen Grenzwert
- den Status eines Gerätes
Genau dafür gibt es in Node-RED den sogenannten Context.
Mit dem Context kannst du Werte speichern, ohne direkt eine Datenbank wie SQLite, InfluxDB oder MySQL zu verwenden. Das ist besonders praktisch für kleine Automationen, einfache Zustände und schnelle Logik innerhalb eines Flows.
Was ist der Node-RED Context?
Der Context ist vereinfacht gesagt ein kleiner Speicherbereich innerhalb von Node-RED.
Du kannst dort Werte ablegen und später wieder abrufen. Das funktioniert ähnlich wie eine Variable in einem Programm, nur dass der Wert nicht nur während einer einzelnen Nachricht existieren muss.
Ein einfaches Beispiel:
Ein Temperaturwert kommt regelmäßig in Node-RED an. Du möchtest prüfen, ob sich der Wert seit der letzten Messung geändert hat. Dafür musst du den vorherigen Wert irgendwo speichern.
Natürlich könntest du dafür eine Datenbank verwenden. Für so eine kleine Aufgabe wäre das aber übertrieben.
Hier reicht der Node-RED Context völlig aus.
Wann ist der Context sinnvoll?
Der Context ist ideal für kleine Zustände und einfache Zwischenspeicher.
Typische Beispiele sind:
- letzter Messwert eines Sensors
- vorheriger Schaltzustand eines Shelly
- Anzahl der Tastendrücke
- letzte MQTT-Nachricht
- letzter Zeitstempel
- aktueller Modus einer Automation
- Merker, ob eine Benachrichtigung bereits gesendet wurde
Ein praktisches Beispiel aus dem Smarthome:
Ein Shelly Plug S liefert regelmäßig seine aktuelle Leistung. Du möchtest aber nicht bei jedem identischen Wert eine neue Aktion auslösen. Also speicherst du den letzten Wert im Context und vergleichst ihn mit dem neuen Wert.
Nur wenn sich der Wert geändert hat, läuft der Flow weiter.
Wann sollte ich lieber eine Datenbank verwenden?
Der Context ist praktisch, aber kein Ersatz für eine richtige Datenbank.
Eine Datenbank ist besser geeignet, wenn du Daten langfristig speichern oder später auswerten möchtest.
Wenn du Messwerte dauerhaft speichern möchtest, ist SQLite eine gute und leichtgewichtige Lösung. Wie du SQLite mit Node-RED verwendest, zeige ich dir in meinem Beitrag „Node-RED mit Docker – SQLite Datenbank anbinden und erste Abfragen“.
Nutze eine Datenbank für:
- Messwerte über Tage, Wochen oder Monate
- Energieverbrauch
- Temperaturverläufe
- Diagramme
- CSV-Export
- historische Auswertungen
- viele Datensätze
Nutze den Context für:
- einzelne Zustände
- letzte Werte
- einfache Merker
- kleine Zähler
- temporäre Logik
Merke dir als einfache Faustregel:
Context ist für Zustände. Datenbanken sind für Historien.
Die drei Context-Arten in Node-RED
Node-RED unterscheidet zwischen drei Bereichen:
- Node Context
- Flow Context
- Global Context
Diese drei Varianten unterscheiden sich darin, wo der gespeicherte Wert sichtbar ist.
Node Context
Der Node Context ist nur innerhalb einer bestimmten Node sichtbar.

Das bedeutet: Nur diese eine Function Node kann den Wert speichern und später wieder abrufen.
Das ist sinnvoll, wenn der Wert wirklich nur in dieser einen Node benötigt wird.
Beispiel:
let zaehler = context.get("zaehler") || 0;
zaehler++;
context.set("zaehler", zaehler);
msg.payload = zaehler;
return msg;
Dieser Code erzeugt einen einfachen Zähler.
Flow als JSON zum Import in Node-RED
[
{
"id": "f5ee6b8ce3d7f0ea",
"type": "tab",
"label": "Beispiel - Node Context",
"disabled": false,
"info": "",
"env": []
},
{
"id": "f4eb283e75ccec08",
"type": "group",
"z": "f5ee6b8ce3d7f0ea",
"name": "Flow 1",
"style": {
"label": true
},
"nodes": [
"9b5afd956de9abc1",
"ac6cdb52ac14f29f",
"a7ee079e7b0ec0ec"
],
"x": 34,
"y": 79,
"w": 572,
"h": 82
},
{
"id": "e0d1008fa6962d21",
"type": "group",
"z": "f5ee6b8ce3d7f0ea",
"name": "Flow 2",
"style": {
"label": true
},
"nodes": [
"f1bd4fcfe79191df",
"7f14fb5dea0406ed",
"0ed25a54054903c9"
],
"x": 34,
"y": 239,
"w": 572,
"h": 82
},
{
"id": "9b5afd956de9abc1",
"type": "inject",
"z": "f5ee6b8ce3d7f0ea",
"g": "f4eb283e75ccec08",
"name": "Start",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 130,
"y": 120,
"wires": [
[
"ac6cdb52ac14f29f"
]
]
},
{
"id": "ac6cdb52ac14f29f",
"type": "function",
"z": "f5ee6b8ce3d7f0ea",
"g": "f4eb283e75ccec08",
"name": "increment value",
"func": "let zaehler = context.get(\"zaehler\") || 0;\n\nzaehler++;\n\ncontext.set(\"zaehler\", zaehler);\n\nmsg.payload = {\n zaehler: zaehler,\n flow: 1\n};\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 300,
"y": 120,
"wires": [
[
"a7ee079e7b0ec0ec"
]
]
},
{
"id": "a7ee079e7b0ec0ec",
"type": "debug",
"z": "f5ee6b8ce3d7f0ea",
"g": "f4eb283e75ccec08",
"name": "print value",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 490,
"y": 120,
"wires": []
},
{
"id": "f1bd4fcfe79191df",
"type": "inject",
"z": "f5ee6b8ce3d7f0ea",
"g": "e0d1008fa6962d21",
"name": "Start",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 130,
"y": 280,
"wires": [
[
"7f14fb5dea0406ed"
]
]
},
{
"id": "7f14fb5dea0406ed",
"type": "function",
"z": "f5ee6b8ce3d7f0ea",
"g": "e0d1008fa6962d21",
"name": "increment value",
"func": "let zaehler = context.get(\"zaehler\") || 0;\n\nzaehler++;\n\ncontext.set(\"zaehler\", zaehler);\n\nmsg.payload = {\n zaehler: zaehler,\n flow: 2\n};\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 300,
"y": 280,
"wires": [
[
"0ed25a54054903c9"
]
]
},
{
"id": "0ed25a54054903c9",
"type": "debug",
"z": "f5ee6b8ce3d7f0ea",
"g": "e0d1008fa6962d21",
"name": "print value",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 490,
"y": 280,
"wires": []
}
]
Bei jedem Durchlauf wird der gespeicherte Wert gelesen, um 1 erhöht und wieder gespeichert.
Flow Context
Der Flow Context ist innerhalb eines kompletten Flow-Tabs sichtbar.

Das bedeutet: Mehrere Nodes auf derselben Arbeitsfläche können auf denselben Wert zugreifen.
Das ist in der Praxis oft die nützlichste Variante.
Beispiel zum Speichern eines Wertes:
flow.set("letzteTemperatur", msg.payload);
return msg;
Beispiel zum Abrufen eines Wertes:
let letzteTemperatur = flow.get("letzteTemperatur");
msg.payload = letzteTemperatur;
return msg;
Damit kannst du einen Wert in einer Function Node speichern und in einer anderen Function Node wieder verwenden.
Flow als JSON zum Import in Node-RED
[
{
"id": "989e20d562ad874b",
"type": "tab",
"label": "Beispiel - Flow Context",
"disabled": false,
"info": "",
"env": []
},
{
"id": "4a2e2396ea5e2544",
"type": "mqtt in",
"z": "989e20d562ad874b",
"name": "",
"topic": "/sensor/temp",
"qos": "0",
"datatype": "auto-detect",
"broker": "2dc0a4b70d96ebb5",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 110,
"y": 180,
"wires": [
[
"bf7938c56e845be4"
]
]
},
{
"id": "68282a22fe7258cd",
"type": "debug",
"z": "989e20d562ad874b",
"name": "print value from MQTT flow",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 940,
"y": 180,
"wires": []
},
{
"id": "bfb362dbabd6e504",
"type": "function",
"z": "989e20d562ad874b",
"name": "save sensor value",
"func": "flow.set(\"letzteTemperatur\", msg.payload || undefined);\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 180,
"wires": [
[
"acdb440a4401a7af"
]
]
},
{
"id": "acdb440a4401a7af",
"type": "function",
"z": "989e20d562ad874b",
"name": "build debug message",
"func": "msg.payload = \"neuer Sensorwert: \" + flow.get(\"letzteTemperatur\");\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 680,
"y": 180,
"wires": [
[
"68282a22fe7258cd"
]
]
},
{
"id": "bf7938c56e845be4",
"type": "switch",
"z": "989e20d562ad874b",
"name": "",
"property": "letzteTemperatur",
"propertyType": "flow",
"rules": [
{
"t": "eq",
"v": "payload",
"vt": "msg"
},
{
"t": "else"
}
],
"checkall": "false",
"repair": false,
"outputs": 2,
"x": 270,
"y": 180,
"wires": [
[
"7795de29b7e93269"
],
[
"bfb362dbabd6e504"
]
]
},
{
"id": "4a28d1dcca1585e9",
"type": "inject",
"z": "989e20d562ad874b",
"name": "Start",
"props": [],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 110,
"y": 60,
"wires": [
[
"3351321a370f12ee"
]
]
},
{
"id": "3351321a370f12ee",
"type": "function",
"z": "989e20d562ad874b",
"name": "create default value",
"func": "flow.set(\"letzteTemperatur\", 0);\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 290,
"y": 60,
"wires": [
[]
]
},
{
"id": "cc074b457a60b73f",
"type": "debug",
"z": "989e20d562ad874b",
"name": "print message",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 640,
"y": 120,
"wires": []
},
{
"id": "7795de29b7e93269",
"type": "function",
"z": "989e20d562ad874b",
"name": "create message",
"func": "msg.payload = \"selben Sensorwert [\" + flow.get(\"letzteTemperatur\") + \"] empfangen.\"\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 440,
"y": 120,
"wires": [
[
"cc074b457a60b73f"
]
]
},
{
"id": "2dc0a4b70d96ebb5",
"type": "mqtt-broker",
"name": "",
"broker": "mosquitto",
"port": 1883,
"clientid": "",
"autoConnect": true,
"usetls": false,
"protocolVersion": 4,
"keepalive": 60,
"cleansession": true,
"autoUnsubscribe": true,
"birthTopic": "",
"birthQos": "0",
"birthRetain": "false",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closeRetain": "false",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willRetain": "false",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": ""
}
]
Global Context
Der Global Context ist in der gesamten Node-RED-Instanz sichtbar.

Das bedeutet: Alle Flows können auf diesen Wert zugreifen.
Das ist sinnvoll für Werte, die wirklich überall benötigt werden.
Beispiele:
- zentrale Konfiguration
- IP-Adresse eines Gerätes
- API-Basisadresse
- globaler Betriebsmodus
- gemeinsam genutzte Grenzwerte
Beispiel:
global.set("shelly_ip", "192.168.178.50");
return msg;
Abrufen kannst du den Wert dann so:
let ip = global.get("shelly_ip");
msg.url = "http://" + ip + "/rpc/Shelly.GetStatus";
return msg;
Hier wird die IP-Adresse eines Shelly-Gerätes zentral gespeichert und später für einen HTTP-Request verwendet.
Beispiel Global Context – Flow #1
[
{
"id": "fee017b8a550cd64",
"type": "tab",
"label": "Beispiel - Global Context #1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "ca2f5066067c72ee",
"type": "inject",
"z": "fee017b8a550cd64",
"name": "Start",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 530,
"y": 60,
"wires": [
[
"605814d58e345769"
]
]
},
{
"id": "605814d58e345769",
"type": "function",
"z": "fee017b8a550cd64",
"name": "set value to global context",
"func": "global.set(\"name\", \"Stefan\")\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 730,
"y": 60,
"wires": [
[]
]
}
]
Beispiel Global Context – Flow #2
[
{
"id": "7037c6aa34965146",
"type": "tab",
"label": "Beispiel - Global Context #2",
"disabled": false,
"info": "",
"env": []
},
{
"id": "be95863731cef366",
"type": "inject",
"z": "7037c6aa34965146",
"name": "Start",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 370,
"y": 60,
"wires": [
[
"cf8196e6d58f8d00"
]
]
},
{
"id": "cf8196e6d58f8d00",
"type": "function",
"z": "7037c6aa34965146",
"name": "build greeting",
"func": "msg.payload = \"Hallo \" + (global.get(\"name\") || \"Hans\");\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 540,
"y": 60,
"wires": [
[
"b6017c014fbeb390"
]
]
},
{
"id": "b6017c014fbeb390",
"type": "debug",
"z": "7037c6aa34965146",
"name": "print message",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 740,
"y": 60,
"wires": []
}
]
Context im Debug-Bereich anzeigen
Node-RED bietet in der Seitenleiste auch eine Context-Ansicht.
Dort kannst du gespeicherte Werte prüfen. Das ist beim Entwickeln sehr hilfreich, weil du sehen kannst, ob dein Wert wirklich gespeichert wurde.

Öffne dazu in Node-RED rechts die Seitenleiste und wähle den Bereich für Context-Daten aus.
Dort findest du getrennte Bereiche für:
- Node
- Flow
- Global
Je nachdem, wo du deinen Wert gespeichert hast, wird er dort angezeigt.
Wichtig: Je nach Ansicht musst du die Context-Daten aktualisieren, damit die Werte sichtbar werden.
Context oder Datenbank?
Hier eine einfache Orientierung:
| Aufgabe | Context | Datenbank |
|---|---|---|
| letzten Sensorwert merken | ja | eher nein |
| Schaltzustand speichern | ja | eher nein |
| einfachen Zähler speichern | ja | möglich |
| Temperaturverlauf speichern | nein | ja |
| Energiedaten auswerten | nein | ja |
| Diagramme über mehrere Tage erstellen | nein | ja |
| kleine Automation steuern | ja | eher nein |
| CSV-Export erstellen | nein | ja |
Der Context ist also ideal für kleine Zustände.
Sobald du Daten sammeln, auswerten oder langfristig speichern möchtest, ist eine Datenbank sinnvoller.
Typische Fehler beim Node-RED Context
Fehler 1: Falscher Context-Bereich
Ein häufiger Fehler ist, dass ein Wert mit context.set() gespeichert wird, später aber mit flow.get() abgerufen werden soll.
Das funktioniert nicht.
Beispiel falsch:
context.set("wert", 123);
let wert = flow.get("wert");
Richtig wäre:
context.set("wert", 123);
let wert = context.get("wert");
Oder:
flow.set("wert", 123);
let wert = flow.get("wert");
Speichern und Abrufen müssen also zum selben Context-Bereich passen.
Fehler 2: Nicht vorhandene Werte abfragen
Wenn ein Wert noch nie gespeichert wurde, liefert get() keinen gültigen Wert zurück.
Deshalb sollte man oft mit einem Standardwert arbeiten.
Beispiel:
let zaehler = flow.get("zaehler") || 0;
Wenn noch kein Zähler existiert, wird automatisch mit 0 gestartet.
Fehler 3: Zu viele Daten im Context speichern
Der Context ist kein Ersatz für eine Datenbank.
Speichere dort keine großen Datenmengen oder komplette Messwert-Historien. Dafür sind SQLite, InfluxDB oder andere Datenbanken besser geeignet.
Was passiert nach einem Neustart von Node-RED?
Ein wichtiger Punkt beim Node-RED Context ist das Verhalten nach einem Neustart.
In der Standardkonfiguration werden Context-Werte im Arbeitsspeicher von Node-RED gespeichert. Das bedeutet: Solange Node-RED läuft, bleiben die Werte verfügbar. Wird Node-RED jedoch neu gestartet, der Docker-Container beendet oder der Raspberry Pi neu gebootet, können diese Werte verloren gehen.
Das sieht man besonders gut bei einem einfachen Zähler:
let zaehler = context.get("zaehler") || 0;
zaehler++;
context.set("zaehler", zaehler);
msg.payload = {
zaehler: zaehler
};
return msg;
Solange Node-RED läuft, zählt dieser Flow sauber hoch.
Nach einem Neustart beginnt der Zähler jedoch wieder bei 0, wenn der Context nicht dauerhaft gespeichert wird. Das ist kein Fehler im Flow, sondern das normale Verhalten, wenn Node-RED den Context nur im Arbeitsspeicher hält.
Für viele kleine Automationen ist das völlig in Ordnung.
Beispiele:
- letzter Sensorwert zum Vergleich
- temporärer Status
- einfacher Merker
- kurzfristige Logik innerhalb eines Flows
Problematisch wird es erst, wenn der Wert dauerhaft erhalten bleiben soll.
Beispiele:
- ein Zählerstand
- ein letzter Schaltzustand
- eine Konfiguration
- ein Betriebsmodus
- ein Grenzwert
In solchen Fällen sollte der Context persistent gespeichert werden. Das bedeutet, dass Node-RED die Werte nicht nur im Arbeitsspeicher hält, sondern zusätzlich im Dateisystem ablegt.
Wie man diesen persistenten Context einrichtet, zeige ich in einem separaten Beitrag. Dort schauen wir uns an, wie die Datei settings.js angepasst wird und worauf man besonders bei Docker achten sollte.
Für diesen Beitrag reicht zunächst die wichtigste Erkenntnis:
Context ist praktisch für kleine Zustände, aber standardmäßig nicht automatisch dauerhaft gespeichert.
Fazit
Der Node-RED Context ist eine einfache Möglichkeit, Werte zu speichern, ohne direkt eine Datenbank verwenden zu müssen.
Für kleine Zustände, letzte Sensorwerte, Zähler oder Merker ist der Context ideal. Gerade bei einfachen Smarthome-Automationen spart man sich dadurch viel Aufwand.
Wichtig ist nur, den passenden Context-Bereich zu wählen:
contextfür eine einzelne Nodeflowfür einen kompletten Flowglobalfür alle Flows
Für langfristige Messwerte, Energieverläufe oder Diagramme bleibt eine Datenbank weiterhin die bessere Lösung.
Letzte Aktualisierung am: 05. Juni 2026







