Skip to content

Persistence

mchristegh edited this page Jul 10, 2026 · 2 revisions

The Resume on deploy/restart option (off by default; see Configuration). When enabled, the node saves its state to disk on every meaningful change and restores it when Node-RED restarts or the flow is redeployed — so a redeploy in the middle of a 15-minute counting cycle doesn't silently discard two counted breaches.

What is saved

Not just a count — the full arrival timestamp of every live counted message, which is what makes accurate restoration possible. Alongside it: the state (idle/counting/cooldown), the cooldown's target end time, the disabled flag, any runtime overrides from setcountlimit / setwindow, the ignored-message tracking, and the last counted message (the clone base for internally-sourced events; see Output Messages).

How each state restores

A counting cycle, sliding mode — the saved timestamps are pruned against the current wall clock, exactly as if the node had been running the whole time. Messages that aged out during the downtime simply fall away. If live messages remain, the node resumes counting at the correct decayed count; if none remain, it settles quietly to idle. This is the most graceful restore in the node: downtime and decay are the same operation.

A counting cycle, fixed mode — the shared window's remaining time is recalculated from its original anchor.

  • Window still has time left → the cycle resumes and expires on its original schedule.
  • Window already elapsed during downtime → the node settles quietly to idle. No retroactive windowexpired is emitted — the restore is not a live transition.
  • Less than 3 seconds left → the remaining time is randomized to 3–8 seconds. This is the same anti-flood rule as the sibling timer-events node: it gives the rest of the flow time to initialize, and prevents many nodes from all firing in the same instant after a restart. The practical consequence: a fixed window that was moments from expiring will expire a few seconds later than it originally would have.

A cooldown — restores directly into cooldown at the recalculated remaining time (randomized to 3–8 seconds if negligible or overdue). Candidates arriving after the restore are blocked as normal.

Idle — nothing live to resume, but the saved context still applies: the disabled flag, runtime overrides, and ignored-message tracking all survive. A node that was disabled before the restart is still disabled after it.

In every case, an active Heartbeat restarts fresh from the restore moment rather than resuming its original schedule.

Two guarantees

  • A restore never fires the Trigger — even if the saved count already meets the limit (possible if setcountlimit lowered the limit and the file predates it, or after an edge-case crash). The Trigger only ever fires on a live counted message; after such a restore, the very next candidate completes the count and triggers.
  • A restore never emits any event at all. No counted replays, no retroactive windowexpired. The flow simply finds the node in the right state. If your flow needs to know a restart happened, an inject node configured to fire once on deploy, sending query, gives you a post-restore snapshot.

File mechanics

State files live in a timerthreshold-timers subdirectory of your Node-RED user directory (userDir in settings.js; defaults to ~/.node-red), one file per node. They are managed entirely by the node — created and updated as state changes, and removed when the node is deleted from a flow or the persistence option is turned off.

Note that the file is not removed when the node merely returns to idle — an idle node can still carry restorable context (the disabled flag, runtime overrides), per the idle restore above.

This mechanism is unrelated to Node-RED's built-in "Persistent Context" (contextStorage in settings.js) — no configuration there is needed or consulted.

Honest limitations

  • The file is written on meaningful state changes, not continuously. A hard crash (power loss, kill -9) can lose whatever happened after the last write — in practice, at most the most recent event.
  • Timestamps are wall-clock. If the system clock jumps significantly between shutdown and restore (a machine without an RTC syncing NTP late, say), the pruning and recalculation arithmetic inherits that jump.
  • If a flow is exported and re-imported, the node receives a new ID and will not find the old node's state file.

Clone this wiki locally