Skip to content

0.13.0 — time-based failure-rate circuit-breaker mode

Choose a tag to compare

@lesnik512 lesnik512 released this 16 Jun 10:53
2087b68

httpware 0.13.0 — time-based failure-rate trip mode for the circuit breaker

Minor release. Additive only — no breaking changes.

This release adds an opt-in time-based failure-rate trip mode to both
AsyncCircuitBreaker and CircuitBreaker. Classic consecutive-failure behavior
is the default and is unchanged.

New behavior

The classic circuit breaker trips after failure_threshold consecutive counted
failures — a simple and effective policy for hard outages. It can miss partial
degradation, though: a downstream returning errors on half of all requests may
never form a long enough consecutive streak to trip the circuit.

Rate mode addresses this. Pass failure_rate_threshold to switch:

from httpware import AsyncClient
from httpware.middleware.resilience import AsyncCircuitBreaker


breaker = AsyncCircuitBreaker(
    failure_rate_threshold=0.5,  # open at ≥50% failures
    window_seconds=30.0,         # over a rolling 30s window
    minimum_calls=20,            # but only once 20+ calls are observed
)

async with AsyncClient(
    base_url="https://api.example.com",
    middleware=[breaker],
) as client:
    response = await client.get("/users/1")

The circuit opens when the observed failure rate over the rolling window_seconds
window meets or exceeds failure_rate_threshold — but only once minimum_calls
outcomes have been recorded in that window. The minimum_calls guard prevents a
single early failure from immediately tripping the circuit before a meaningful
sample has accumulated.

New constructor parameters

Both AsyncCircuitBreaker and CircuitBreaker accept three new keyword
arguments:

Parameter Default Effect
failure_rate_threshold None Float in (0, 1]. When set, switches the breaker to rate mode. None keeps classic consecutive-failure mode. ≤0 or >1 raises ValueError.
window_seconds 30.0 Rolling window width for rate mode. Ignored in classic mode. ≤0 raises ValueError.
minimum_calls 20 Minimum outcomes in the window before the rate is evaluated. Ignored in classic mode. <1 raises ValueError.

In rate mode, failure_threshold is ignored — the trip condition is purely
rate-based. All other parameters (reset_timeout, success_threshold,
failure_status_codes) apply in both modes.

Observability

Event names are identical in both modes: circuit.opened, circuit.rejected,
circuit.half_open, circuit.closed. In rate mode the circuit.opened event
carries additional attributes — failure_rate, failure_rate_threshold,
window_seconds, observed_calls — and its message is
"circuit opened — failure rate threshold reached".

What is NOT in this release

The following remain deferred and are not part of 0.13.0:

  • Count-based sliding windows (the current implementation is time-based only)
  • Slow-call detection (a separate trip axis based on latency percentiles)
  • Manual circuit control (force_open, force_closed)
  • State introspection properties on the breaker instance

Shipped via

PR #69 — time-based failure-rate trip mode for the circuit breaker.