You have a signal that at every observation tells you which state you're in: a health monitor that says OK or CAÍDO, a connectivity detector, a mode classifier. And near the threshold it oscillates: OK, CAÍDO, OK, CAÍDO, OK. Every change fires something —an alert, a failover, entering or exiting a position— and suddenly your system is shaking from noise, not from a real transition.
It's the same problem your home thermostat has been solving for a century, and the solution has a name: hysteresis. Don't change state until the new one has held.
The rule, in one sentence
A new state is only confirmed after it repeats for N consecutive observations. If the candidate changes or reverts before reaching N, the count resets. The current state stays stable; the flapping is ignored.
I packaged it as a library —hysteresis-state, pure Python, no dependencies— because I kept rewriting it over and over:
from hysteresis_state import HysteresisState
estado = HysteresisState("OK", confirmations=3)
for lectura in stream: # "OK" / "CAIDO"
actual = estado.update(lectura) # only changes after 3 readings in a row
if estado.changed: # did this reading cause the transition?
alertar(actual)
Feed it OK, CAÍDO, OK, CAÍDO, OK and nothing happens: no candidate held. It takes three CAÍDO in a row for the change to be confirmed.
The detail that's almost always missing: asymmetric hysteresis
A single threshold has a subtle problem. If you require 3 confirmations to enter failure, you also take 3 to leave it — and sometimes you want exactly the opposite: fall fast to safety, return slowly to risk. It's the behaviour of an electrical circuit breaker: it trips at the first fault, and re-arms with caution.
It's solved by letting the threshold depend on the transition:
# 1 confirmation to fall to "CAIDO", 5 to return to "OK"
conf = lambda desde, hacia: 1 if hacia == "CAIDO" else 5
estado = HysteresisState("OK", confirmations=conf)
estado.update("CAIDO") # falls instantly
# ...now it takes 5 "OK" in a row to return
Why "averaging" isn't enough
The temptation is to smooth with a moving average and threshold that. It works for numeric signals, but it breaks with discrete states (you don't average OK and CAÍDO), it introduces lag into every transition equally, and it doesn't give you the asymmetry above. Confirmation-based hysteresis is the right tool when what oscillates is a label, not a number.
Where it came from
This was born inside a trading bot. Its regime brain classified the market into trend / range / chaos, and near the thresholds it flapped: each flap froze or reactivated trading, which is exactly what you don't want happening because of noise. Hysteresis calmed it down. But the mechanism knows nothing about markets —it's anti-flapping for any discrete signal—, so I released it.
It's free software. Since August 2026 the code isn't published to registries or on GitHub —we work in security, and having our source extracted would be an argument against the product—: it's delivered on request, signed and with its SHA-256, at contacto@xiliux.com.
Code and tests (with the counting and asymmetry edge cases, verified by mutation): **.
Xiliux