Skip to main content

interlock

CI Coverage OpenSSF Scorecard OpenSSF Best Practices PyPI Downloads Python versions License: MIT llms.txt Documentation Context7 CodSpeed

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.

Installation

uv add interlock-cb          # or: pip install interlock-cb

interlock-cb supports Python 3.11 and newer. The core uses only the standard library; external integrations are installed as optional extras.

Quickstart

Create one named breaker and reuse it around calls to the same dependency:

from interlock import CircuitBreaker, CircuitOpenError, Config

breaker = CircuitBreaker(
    name='payments',
    config=Config(failure_rate_threshold=0.5, minimum_number_of_calls=20),
)


@breaker
def charge(amount: int) -> str:
    return gateway.charge(amount)


try:
    receipt = charge(100)
except CircuitOpenError as exc:
    print(exc)

The decorator preserves the function's signature and whether it is sync or async. The same breaker also supports breaker.call(fn, ...), with breaker, and async with breaker. See Getting started for all calling styles and Configuration for every threshold.

Why interlock

  • Sync and async, one class. CircuitBreaker dispatches to separate sync and async paths without duplicating the public API.
  • Failure rates over sliding windows. Choose count- or time-based windows instead of relying only on consecutive failures.
  • Slow calls and returned values count. Detect latency degradation and classify unsuccessful results even when no exception is raised.
  • Type-safe decorators. Wrapped signatures and their sync/async nature are preserved; the package ships py.typed and passes three strict type checkers.
  • Zero-dependency core. Optional clients, frameworks, storage and observability integrations never leak into the core package.
  • Composable resilience. Combine timeout, bulkhead, breaker, retry and fallback explicitly, or coordinate breaker state across instances with Redis.

Safe production rollout

Start a new integration in METRICS_ONLY to observe real failure and slow-call rates without rejecting traffic. The initial state is applied before a lazy per-host breaker can admit its first request:

import httpx2

from interlock import Config, State
from interlock.integrations.httpx2 import AsyncCircuitBreakerTransport

transport = AsyncCircuitBreakerTransport(
    httpx2.AsyncHTTPTransport(),
    initial_state=State.METRICS_ONLY,
    config=Config(failure_rate_threshold=0.25, minimum_number_of_calls=50),
    listener=metrics_listener,
)

Use an EventListener for production metrics. For local diagnostics, transport.registry.get_existing(host) returns an already-created breaker without creating one, so its state and snapshot() can be inspected safely. After tuning thresholds, deploy a new transport with the default initial_state=State.CLOSED; the enforcing instance starts with a fresh window. See States and manual control.

Resilience pipeline

Compose strategies in an explicit order (first is outermost) while keeping the breaker useful as a standalone primitive:

from interlock import CircuitBreaker, CircuitOpenError, Pipeline

breaker = CircuitBreaker(name='recommendations')

pipeline = (
    Pipeline.builder()
    .fallback(lambda exc: [], on=(CircuitOpenError,))
    .retry(attempts=4)  # requires interlock-cb[tenacity]
    .circuit_breaker(breaker)
    .bulkhead(8)
    .timeout(2.0)
    .build()
)


@pipeline
async def fetch_picks(user: str) -> list[str]:
    return await client.get_picks(user)

Retries never hammer an open circuit, one hung attempt cannot eat the retry budget, and every decision is observable — see the pipeline guide.

Integrations

The httpx2 transport applies one breaker per host with no decorators at call sites:

import httpx2
from interlock.integrations.httpx2 import CircuitBreakerTransport

transport = CircuitBreakerTransport(httpx2.HTTPTransport())
client = httpx2.Client(transport=transport)

By default, transport exceptions and the canonical retryable statuses (429, 500, 502, 503, 504) count as failures; 4xx client errors do not.

Integration Install Documentation
httpx2 interlock-cb[httpx2] Per-host transport
httpx interlock-cb[httpx] Per-host transport
aiohttp interlock-cb[aiohttp] Client middleware
requests interlock-cb[requests] Session adapter
FastAPI interlock-cb[fastapi] 503 + Retry-After handler
Litestar interlock-cb[litestar] 503 + Retry-After handler
tenacity interlock-cb[tenacity] Retry composition
Redis interlock-cb[redis] Shared state
OpenTelemetry interlock-cb[otel] Metrics listener

The integrations overview also includes recipes for LLM SDKs and Flask/Django.

How it compares

interlock-cb is young: its first release was in 2026. Established libraries such as pybreaker and circuitbreaker have carried production traffic for years and remain a better fit when maturity matters more than the feature differences.

Feature interlock-cb pybreaker circuitbreaker
Core states (closed / open / half-open)
Native asyncio Tornado
Trip condition failure rate consecutive failures consecutive failures
Time-based sliding window
Slow-call detection
Shared state across processes
Composable resilience pipeline
Fully typed API (py.typed)

The full comparison covers more features as well as aiobreaker and purgatory. Something out of date or unfair? Please open a PR.

The reliability work compensating for the project's shorter production history includes 100% branch coverage, three strict type checkers, mutation testing of the state machine and engine, property- and model-based tests, and CI on free-threaded CPython. The correctness and testing page documents what is verified and where the limits are.

Documentation

The full documentation is hosted at https://bagowix.github.io/interlock/. Start with:

For a deterministic, network-free demonstration of every state transition, run the examples/ scripts or follow the walkthrough.

Contributing

Bug reports and pull requests are welcome. See CONTRIBUTING.md for the local setup and the checks a change must pass, and CODE_OF_CONDUCT.md for community expectations. Security issues: please follow SECURITY.md.

License

interlock is released under the MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

interlock_cb-2.4.0.tar.gz (422.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

interlock_cb-2.4.0-py3-none-any.whl (73.3 kB view details)

Uploaded Python 3

File details

Details for the file interlock_cb-2.4.0.tar.gz.

File metadata

  • Download URL: interlock_cb-2.4.0.tar.gz
  • Upload date:
  • Size: 422.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for interlock_cb-2.4.0.tar.gz
Algorithm Hash digest
SHA256 bbd827b5282d648c67c2ea3420c22f81ffc63144200532b84c1f5efb8adb3201
MD5 e56be411c32de8f01939f8cea127370a
BLAKE2b-256 fa594c2dfc37441669e3fbee279fb6e324c640c75b2d89333523869d90391f19

See more details on using hashes here.

Provenance

The following attestation bundles were made for interlock_cb-2.4.0.tar.gz:

Publisher: release.yml on bagowix/interlock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file interlock_cb-2.4.0-py3-none-any.whl.

File metadata

  • Download URL: interlock_cb-2.4.0-py3-none-any.whl
  • Upload date:
  • Size: 73.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for interlock_cb-2.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5514a3ac130983e36d701d0c2245f96a3d397aaed639722941f693887c394404
MD5 4f500601db0e176c18a18c9324e16e5b
BLAKE2b-256 e6f19b8159c07db40c41617c5c26d90e682451a5e08dbf09d2fa0d3761778a6d

See more details on using hashes here.

Provenance

The following attestation bundles were made for interlock_cb-2.4.0-py3-none-any.whl:

Publisher: release.yml on bagowix/interlock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.7.0

2 files

2.6.1

2 files

2.6.0

2 files

2.5.0

2 files

This release

2.4.0 This release

2 files

2.3.0

2 files

2.2.0

2 files

2.1.4

2 files

2.1.3

2 files

2.1.2

2 files

2.1.1

2 files

2.1.0

2 files

2.0.0

2 files

1.3.0

2 files

1.2.0

2 files

1.1.0

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page