El contexto de Node-RED es el almacenamiento clave-valor integrado que permite a un flujo recordar valores entre mensajes, como la última temperatura que informó un sensor o un contador de las alarmas de hoy. Esta guía explica los tres ámbitos de contexto, cómo hacer que el contexto sobreviva a los reinicios, cómo usar varios almacenes a la vez y un patrón limpio para conservar el último valor MQTT de cada dispositivo.
Por qué los flujos necesitan estado
Los mensajes en Node-RED son independientes. Cuando un nodo mqtt in emite una lectura, el siguiente nodo solo conoce lo que hay dentro de ese mensaje. Muchas tareas reales necesitan más que eso:
- Comparar un valor con el anterior para detectar un cambio o una tendencia.
- Responder a una petición HTTP con la lectura más reciente, aunque en ese momento no esté llegando ningún mensaje MQTT.
- Contar eventos por turno o recordar cuándo empezó una alarma.
- Combinar valores de dos topics que llegan en momentos distintos.
MQTT ofrece por sí mismo una forma de memoria mediante los mensajes retenidos, en los que el broker guarda el último mensaje de un topic y lo entrega a los nuevos suscriptores. Es ideal para el estado compartido entre clientes, y deberías usarlo. El contexto es la herramienta complementaria para el estado que vive dentro de Node-RED. Si no tienes claro a qué lado corresponde una responsabilidad, nuestra explicación sobre qué hace un broker MQTT traza la línea.
Los tres ámbitos de contexto de Node-RED
| Ámbito | Visible para | Uso típico | Acceso en una función |
|---|---|---|---|
| Node | Solo el nodo que lo definió | Filtros de banda muerta, contadores dentro de una función | context.get() / context.set() |
| Flow | Todos los nodos de la misma pestaña (o dentro de la misma instancia de subflujo) | Últimos valores usados por varios nodos de una pestaña | flow.get() / flow.set() |
| Global | Todos los nodos de la instancia de Node-RED | Configuración compartida, tablas de consulta | global.get() / global.set() |
Elige el ámbito más reducido que funcione. Cualquier nodo de cualquier pestaña puede cambiar un valor del contexto global, lo que hace que los errores sean difíciles de rastrear. El contexto de nodo es privado, así que nada más puede romperlo.
No necesitas escribir código para usar el contexto. El nodo Change puede asignar, leer, mover y eliminar propiedades flow. y global., y los nodos Inject, Switch y Template pueden leerlas. La pestaña Context Data de la barra lateral del editor muestra los valores actuales de cada ámbito y te permite actualizarlos o eliminar entradas mientras depuras.
Los subflujos tienen un matiz adicional: el contexto flow dentro de un subflujo pertenece a esa instancia. Un subflujo puede acceder al contexto del flujo padre con el prefijo $parent., por ejemplo flow.get("$parent.lastTemp").
Contexto en memoria frente a contexto persistente
Por defecto todo el contexto se guarda en memoria. Es rápido, pero desaparece cuando Node-RED se reinicia, cuando se recrea el contenedor o cuando el host se reinicia. Para cualquier cosa que no puedas reconstruir fácilmente, activa el almacenamiento en archivo.
Abre settings.js (en ~/.node-red/ en una instalación estándar, o en /data/ en la imagen de Docker) y busca la sección contextStorage:
// settings.js
module.exports = {
// ...
contextStorage: {
default: { module: "memory" },
file: { module: "localfilesystem" }
},
// ...
};
Reinicia Node-RED. Ahora tienes dos almacenes: default, que se queda en memoria, y file, que escribe archivos JSON en la carpeta context/ de tu directorio de usuario. Los nodos eligen el almacén explícitamente:
flow.set("lastReading", msg.payload, "file"); // persistente
flow.set("scratch", 42); // memoria (almacén predeterminado)
const last = flow.get("lastReading", "file");
En el nodo Change y otros editores aparece un pequeño selector de almacén junto a los campos flow. y global. en cuanto tienes más de un almacén.
Si prefieres que todo sea persistente, configura default: { module: "localfilesystem" }. Ten en cuenta cómo funciona el almacén en archivo: los valores se guardan en caché en memoria y se escriben en disco a intervalos, cada 30 segundos por defecto, según la opción flushInterval. Un fallo grave puede perder los cambios de los últimos segundos. Eso está bien para últimos valores y contadores, pero el contexto no es una base de datos. Para datos históricos, escribe en un almacén de series temporales como InfluxDB, como se muestra en nuestra guía de Node-RED con InfluxDB.
Ten en cuenta también que solo los valores serializables en JSON persisten de forma fiable. Las funciones, los temporizadores y las instancias de clase no volverán intactos tras un reinicio, así que guarda objetos simples, números y cadenas.
Acceso síncrono y asíncrono
Con los almacenes memory y localfilesystem, get y set funcionan de forma síncrona, como se ha mostrado. Algunos almacenes de terceros, como los módulos basados en Redis, son asíncronos y requieren callbacks:
flow.get("count", "redis", (err, count) => {
if (err) { node.error(err, msg); return; }
count = (count || 0) + 1;
flow.set("count", count, "redis", (err) => {
if (err) { node.error(err, msg); return; }
msg.payload = count;
node.send(msg);
node.done();
});
});
Escribir el código con callbacks desde el principio cuesta poco y te permite cambiar de almacén más adelante sin reescribir cada función. Ten presente que un get seguido de un set no es atómico. Con tasas de mensajes muy altas en un almacén asíncrono, dos mensajes pueden leer el mismo contador antiguo. Mantén los contadores en el contexto de nodo, donde solo un nodo los escribe, o agrupa las actualizaciones.
También puedes leer y escribir varias claves a la vez pasando arrays: flow.get(["a", "b"]) devuelve un array de valores.
Patrón: conserva el último valor MQTT de cada dispositivo
Una tarea habitual del contexto de Node-RED es una tabla en vivo de "último valor conocido": una entrada por dispositivo, actualizada con cada mensaje y legible desde cualquier punto del flujo. Publica algunos datos de prueba en el servidor MQTT público gratuito de ConnectMQ, sustituyendo c8d1 por tu propia cadena aleatoria:
mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-ctx-c8d1 \
-t "connectmq/demo/c8d1/boiler/tank1/telemetry" -m '{"level": 71.5, "temp": 63.2}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-ctx-c8d1 \
-t "connectmq/demo/c8d1/boiler/pump2/telemetry" -m '{"rpm": 1450, "temp": 41.0}'
Suscríbete en Node-RED con un nodo mqtt in en connectmq/demo/c8d1/+/+/telemetry, con la salida configurada como JSON analizado, y conéctalo a esta función:
// Función "store latest"
const parts = msg.topic.split("/");
const deviceId = parts[3] + "/" + parts[4]; // p. ej. "boiler/tank1"
const latest = flow.get("latest", "file") || {};
latest[deviceId] = {
values: msg.payload,
ts: Date.now()
};
flow.set("latest", latest, "file");
node.status({ text: Object.keys(latest).length + " devices" });
return null;
Ahora cualquier nodo de la pestaña puede leer la tabla. Un nodo http in en GET /latest seguido de esta función y de un nodo http response te da una pequeña API:
// Función "serve latest"
const latest = flow.get("latest", "file") || {};
const staleMs = 5 * 60 * 1000;
const now = Date.now();
msg.payload = Object.entries(latest).map(([id, v]) => ({
device: id,
values: v.values,
ageSeconds: Math.round((now - v.ts) / 1000),
stale: now - v.ts > staleMs
}));
return msg;
El indicador stale es el detalle importante. Una tabla de últimos valores que nunca caduca mostrará tan tranquila la lectura de un dispositivo que dejó de funcionar ayer. Guarda siempre una marca de tiempo junto al valor.
Lista de buenas prácticas del contexto en Node-RED
- Usa el ámbito más reducido: node, después flow y, por último, global.
- Activa un almacén en archivo y elígelo explícitamente para los valores que no puedas reconstruir.
- Guarda marcas de tiempo junto a los valores para detectar datos obsoletos.
- Evita objetos enormes; las entradas de contexto grandes ralentizan cada volcado a disco y cada actualización de la barra lateral.
- Pon prefijos a las claves globales según su propósito, por ejemplo
cfg_para configuración ycache_para datos de consulta. - No guardes secretos en el contexto. Las credenciales van en nodos de configuración y variables de entorno.
- Usa mensajes MQTT retenidos para el estado que necesitan otros clientes, y el contexto para el estado que solo necesita Node-RED.
- Haz copia de seguridad de la carpeta
context/junto con tus flujos. ¿Ejecutas Node-RED en contenedores? Nuestra guía de Node-RED en Docker muestra cómo mantener/dataen un volumen persistente.
La documentación oficial del contexto cubre por completo la API de los almacenes y las opciones de configuración. Para la parte de código de estos patrones, consulta nuestra guía del nodo function de Node-RED, y para la visión general de cómo conectar flujos con brokers, el tutorial de Node-RED MQTT.
Combina el contexto de Node-RED con ConnectMQ
El contexto conserva la memoria propia de Node-RED; el broker conserva la de todos los demás. ConnectMQ es un broker MQTT gestionado con mensajes retenidos, caducidad de sesión de MQTT 5 y TLS, de modo que dispositivos, paneles y Node-RED ven los mismos últimos valores conocidos. Su portal añade un explorador de topics en directo y reglas de alerta por umbral para comprobaciones rápidas sin necesidad de crear un flujo. Empieza con el plan Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y conecta Node-RED con el usuario, la contraseña y el client ID generados.
Preguntas frecuentes
¿Cuál es la diferencia entre el contexto flow y el global en Node-RED?
El contexto flow solo lo comparten los nodos de la misma pestaña, mientras que el contexto global lo comparten todos los nodos de la instancia de Node-RED. Usa el contexto flow salvo que varias pestañas necesiten realmente el mismo valor.
¿Cómo hago que el contexto de Node-RED sobreviva a un reinicio?
Añade un almacén localfilesystem en contextStorage dentro de settings.js, reinicia Node-RED y escribe en ese almacén, por ejemplo flow.set("key", value, "file").
¿Dónde guarda Node-RED los archivos de contexto persistente?
En una carpeta context dentro del directorio de usuario de Node-RED, normalmente ~/.node-red/context o /data/context en Docker, organizada por ámbito.
¿Debo usar contexto o mensajes MQTT retenidos para los últimos valores?
Usa mensajes retenidos cuando otros clientes MQTT necesiten el último valor, y el contexto cuando solo lo necesite Node-RED, por ejemplo para servir una API o comparar lecturas. Muchos flujos usan ambos.



