interlock¶
A modern circuit breaker for Python — sync and async in a single class, sliding-window rate and slow-call detection, a type-safe API, and transparent integrations at the transport level.
Why interlock¶
- Sync and async, one class. A single
CircuitBreakerdetects coroutine callables and dispatches to the right path — noSync*/Async*twins. - Sliding windows by rate. Both count-based and time-based windows, not the naive consecutive-failure counter found elsewhere in the ecosystem.
- Slow-call detection. Treat calls slower than a threshold as failures — not available in any other Python circuit breaker.
- Type-safe.
ParamSpec+TypeVardecorators that preserve signatures; shipspy.typedand passes mypy in strict mode. - Zero-dependency core. Standard library only; everything external lives in optional extras.
- Safe production rollout. Start in
METRICS_ONLYto observe real traffic without rejecting it, then enable enforcement with tuned thresholds. - Thread-safe, and checked. One
threading.Lockguards the critical sections; your callable runs outside it. CI drives a single breaker from many threads at once — on free-threaded CPython (3.14t) as well as the GIL builds — so the guarantee is verified, not merely asserted. - Distributed state (optional). Coordinate tripping and recovery probing across instances through Redis/Valkey, with graceful degradation to local state — see the Redis integration.
Choosing between libraries? See the honest comparison with pybreaker, circuitbreaker, aiobreaker and purgatory.
Installation¶
At a glance¶
from interlock import CircuitBreaker, CircuitOpenError
breaker = CircuitBreaker(name='payments')
@breaker
def charge(amount: int) -> str:
return gateway.charge(amount)
try:
charge(100)
except CircuitOpenError as exc:
... # rejected fast: the dependency is unhealthy; retry after exc.retry_after
The same instance protects async callables, works as a (sync and async) context
manager, and can be called directly via breaker.call(fn, ...) — start with
Getting started.
Status¶
interlock shipped a polished core first (state machine, windows, sync/async,
slow-call detection), then grew deliberately: v1.1 added timeouts, proactive
OPEN → HALF_OPEN and FastAPI; v1.2 added coordinated distributed state over
Redis; v1.3 added the integrations wave — aiohttp, requests and
retry × breaker composition via tenacity; v2.0 composes
it all declaratively in the resilience pipeline —
timeout, bulkhead, breaker, retry and fallback around the same standalone
breaker.