Skip to content

Sources Freshness and Quorum

mchristegh edited this page Jul 15, 2026 · 1 revision

The trust layer — the part that separates this node from plain averaging. This page owns source identity, staleness, quorum, the quorum-lost policy, and minority reports.

Source identity

Sources are keyed by msg.topic and hold exactly one latest value each with its lastSeen timestamp — this is not a history node. A reading with a missing topic is rejected (ignored: true).

Sources are learned on first reading (sourceadded). Optionally, the Expected Sources config declares the roster up front: expected sources appear in every snapshot from deploy, marked seen: false until their first reading. That makes "sensor 3 never came back after the power cut" visible in a query, instead of silently absent.

A decommissioned sensor is dropped with the remove command; reset clears all learned sources but keeps the expected roster (as never-seen). See Input Messages.

Staleness

The Staleness Window is how long a source's latest value is trusted. A source that goes quiet past the window is marked stale on the node's own clock — a dead sensor produces no message, so the node must notice on its own — excluded from the aggregate, and announced with sourcestale (source: "internal"). Its next reading marks it fresh again with sourcerecovered.

With the window at 0 (the default), staleness is disabled and last values are held indefinitely — the zero-config behavior for a group of healthy sensors, and exactly the failure mode to avoid for anything battery-powered.

The window can be changed at runtime with setstale, which takes effect immediately in both directions: a shrunk window can expire sources on the spot (sourcestale with source: "external" — the one path where staleness is externally caused), and a widened or disabled window can freshen sources whose data is now back inside it.

Each source expires on its own schedule — two sensors that last reported at different times go stale at different times.

Quorum

Quorum is the minimum number of fresh sources required for trigger/release evaluation (0 = disabled). Below quorum:

  • The aggregate is still computed from whatever is fresh and reported on every event with msg.quorum: false.
  • Trigger/release evaluation is suspended — the latch neither fires nor releases from thresholds.
  • Crossing the boundary emits quorumlost / quorumregained on output 4.

On Quorum Lost While Latched

The genuinely application-dependent decision, so it's yours to configure:

Policy Behavior
Hold (default) The latch keeps its last consensus; state stays triggered with quorum: false until data returns. A dehumidifier probably holds.
Release Quorum loss releases immediately — a genuine Release on outputs 2 + 4 with releaseReason: "quorumlost". An alarm probably fails safe.

One documented edge: a Release-policy node restoring from persistence into quorum-lost stays latched until the first live evaluation, because restore never fires transitions by itself — see Persistence.

Minority reports (Boolean mode)

When a consensus exists (quorum satisfied and the fraction not exactly split), any fresh source disagreeing with the consensus value is a minority. The minorityreport event carries the set in msg.minorityTopics, and fires when the set changes — including one final report with an empty set when the disagreement resolves. A persistently stuck sensor therefore produces exactly one report, not a stream. (Numeric-mode divergence detection is a recorded deferral in the design document; the Trimmed Mean aggregation blunts numeric outliers in the meantime — see Type Modes.)

See it in action: Examples Staleness and Quorum and Examples Boolean Voting.

Clone this wiki locally