-
-
Notifications
You must be signed in to change notification settings - Fork 0
Window Modes
The node's most consequential setting. Both modes answer the same question — did N messages arrive within Y time? — but they define "within Y time" differently, and nearly every mode-dependent behavior in the node follows from that one difference.
| Fixed | Sliding | |
|---|---|---|
| The window is… | One shared clock, anchored to the first message of a cycle | A per-message lifetime — each message is relevant for Y after its own arrival |
| The count… | Only grows (until trigger or expiry) | Can decay stepwise as individual messages age out |
| The cycle ends without a Trigger when… | The shared clock expires — everything resets at once | The last live message ages out (decay to zero) |
| Triggers when… | Count reaches the limit before the shared clock expires | N messages are all live at once — i.e. N arrivals within any Y-long span |
The first counted message starts a Y-duration countdown. Every
subsequent counted message increments the count. If the count reaches
the limit before the countdown ends, the Trigger fires immediately. If
the countdown ends first, the entire count resets at once
(windowexpired on output 3) and the node returns to idle.
Configuration: limit 3, window 15 min, FIXED
0:00 message → count 1, 15-minute clock starts
0:30 message → count 2
1:00 message → count 3 → TRIGGER (immediately - the remaining
14 minutes are irrelevant)
The blind spot to understand: because the clock anchors to the first message, a cluster that straddles a window boundary never triggers.
Configuration: limit 3, window 15 min, FIXED
0:00 message → count 1, clock starts
14:00 message → count 2
15:00 clock expires → count resets to 0, windowexpired
16:00 message → count 1, NEW clock starts
17:00 message → count 2
Three messages arrived within 3 minutes of each other (14:00–17:00), but no Trigger — the boundary split them. If that bothers you, you want sliding mode.
Each counted message is individually relevant for Y after its own arrival, then ages out. On every arrival the node prunes aged-out messages, adds the new one, and checks the count. There is no single window expiry — the window effectively slides continuously.
The same straddling cluster in sliding mode:
Configuration: limit 3, window 15 min, SLIDING
0:00 message → count 1
14:00 message → count 2
15:00 the 0:00 message ages out → count decays to 1 (silently)
16:00 message → count 2
17:00 message → count 3 → TRIGGER
(the 14:00, 16:00, and 17:00 messages are all live at once)
The count can drop on its own as messages age out. Intermediate decay
is silent — no event is emitted; the decayed count is observable via
the status label, a query, or a Heartbeat tick. Only decay to
zero — the last live message aging out — emits an event, because
that is the counting → idle transition.
Configuration: limit 3, window 3 min, SLIDING
0:00 message → count 1
2:00 message → count 2
3:00 the 0:00 message ages out → count 1 (no event)
5:00 the 2:00 message ages out → count 0 (windowexpired, idle)
If you are watching the count via query and it drops without any message arriving, this is why. It is the entire point of sliding mode, not a bug — see Troubleshooting.
- The Trigger fires immediately on the message that completes the count — the node never waits for a window to close.
- The counting → idle transition without a Trigger emits the same event
name,
windowexpired, in both modes (fixed: the shared clock ran out; sliding: decay to zero). The envelope'smsg.windowModefield distinguishes them if a downstream flow cares. See Events. - Commands, gating, Cooldown, and Heartbeat behave identically in both modes.
msg.windowRemaining (see Output Messages): in fixed mode,
milliseconds until the shared window expires. In sliding mode,
milliseconds until the oldest live message ages out — the moment
the count will next change.
Status label (see States): fixed shows
Counting: 2/3 | Window: 00:12:30; sliding shows
Counting: 2/3 | Oldest expires: 00:01:42. Same value semantics as
windowRemaining above.
setwindow re-evaluation (see Input Messages): changing the
window at runtime re-evaluates a live cycle immediately. Fixed mode
re-anchors from the original window start — if the new, shorter window
has already elapsed, the cycle expires right away. Sliding mode
re-prunes every live message against the new duration — if all of them
age out under it, that is a decay to zero.
Persistence restore: sliding mode persists every live message's timestamp and prunes them against the wall clock on restore — messages that aged out during downtime simply fall away, and the node resumes at the correct decayed count. Fixed mode recalculates the shared clock's remaining time from its original anchor.
Sliding matches what people usually mean by "N times in Y minutes" — it detects any sufficiently dense cluster, with no boundary blind spot. It is the better default for sensor-noise debouncing.
Fixed is simpler to reason about, gives the operator a single concrete deadline ("the window closes at 10:45"), and resets cleanly. It suits cases where the first event meaningfully opens an evaluation period — "after the first fault, we allow 15 minutes to see whether it repeats."
Getting Started
Reference
Features
Examples
Test Script Coverage
Support