Integrations¶
interlock plugs into the HTTP client, framework or retry library you already use — you configure thresholds once and the breaker applies per host (or per named dependency) with no decorators in call sites.
Supported integrations¶
| Integration | Extra | What you get |
|---|---|---|
| FastAPI | interlock-cb[fastapi] |
Depends-injected breakers and a CircuitOpenError → 503 + Retry-After handler |
| Litestar | interlock-cb[litestar] |
Provide-injected breakers and a CircuitOpenError → 503 + Retry-After handler (Litestar ≥ 2.23) |
| httpx2 | interlock-cb[httpx2] |
CircuitBreakerTransport / AsyncCircuitBreakerTransport — per-host breaker at the transport level |
| httpx | interlock-cb[httpx] |
CircuitBreakerTransport / AsyncCircuitBreakerTransport — per-host transport for httpx clients |
| aiohttp | interlock-cb[aiohttp] |
CircuitBreakerMiddleware — per-host breaker as a client middleware (aiohttp ≥ 3.12) |
| requests | interlock-cb[requests] |
CircuitBreakerAdapter — per-host breaker mounted on a Session |
| LLM SDKs | — (recipe) | Guard OpenAI / Anthropic SDK calls with a breaker + bounded retries |
| tenacity | interlock-cb[tenacity] |
Retry × breaker glue: stop retrying when the circuit opens, or wait exactly until the next probe |
| Redis | interlock-cb[redis] |
Shared breaker state across processes with graceful degradation |
| Flask / Django | — (recipe) | Map CircuitOpenError to 503 + Retry-After in other web frameworks |
How integrations are built¶
Every integration follows the same rules, so learning one means knowing all:
- Native extension points only. A transport (httpx2/httpx), a client middleware (aiohttp), an adapter (requests), an exception handler (FastAPI). No monkey-patching, no private APIs — an integration survives minor releases of its host library.
- One breaker per host. HTTP integrations key breakers by request host:
a failing
api.anever tripsapi.b. Breakers are created lazily in a sharedRegistry. - Safe rollout before enforcement. Pass
initial_state=State.METRICS_ONLYto record real traffic without rejecting it. The state is applied before each lazy breaker serves its first request; deploy a new integration withCLOSEDafter tuning thresholds. - One classification model. Responses are classified by an
HttpStatusClassifier— by default the canonical retryable set (429, 500, 502, 503, 504) plus every non-excluded transport exception counts as a failure, while4xxclient mistakes do not. Exceptions the caller caused say nothing about the dependency's health, so each integration excludes the ones its own library raises inside the guarded call:UnsupportedProtocol/LocalProtocolErrorfor httpx2 and httpx,InvalidURLfor requests, nothing for aiohttp (it rejects malformed URLs before the middleware chain runs). PassHttpStatusClassifier(failure_statuses={...}, excluded_exceptions=(...))or your ownFailureClassifierto change the policy. - One rejection signal, in two dialects. An open circuit always raises
CircuitOpenError— carrying the breaker name, aretry_afterestimate and the last recorded failure — before a connection is attempted. Each HTTP client integration raises a subclass that is also a native error of that library, so an application's existing degradation path catches it:CircuitOpenTransportError(anhttpx.TransportErrorfor the httpx integration, anhttpx2.TransportErrorfor the httpx2 one),CircuitOpenClientError(anaiohttp.ClientConnectionError),CircuitOpenRequestError(arequests.exceptions.ConnectionError). The host base is always the broadest "the request never completed" type, never a leaf such asConnectError— leaves are what retry predicates key on, and retrying a rejection only burns an attempt against a circuit that is still open. - Zero-dependency core. Integrations live in
interlock.integrations.*as optional extras;import interlockitself never pulls anything beyond the standard library. - Explicit ownership and teardown. Transports and adapters close their
native connection resources together with their breaker registry. The
aiohttp middleware exposes
aclose()becauseClientSessiondoes not own middleware resources.
Support tiers¶
- Tier 1 — shipped code. Modules under
interlock.integrations.*, covered by the test suite and CI against both the minimum supported and the latest version of the host library. Semver applies. - Tier 2 — recipes. Documented, runnable patterns (LLM SDKs, Flask/Django) that need no dedicated glue code. They can graduate to Tier 1 when demand shows up.
Missing an integration — gRPC, SQLAlchemy, Kafka, Celery? Open an issue: the next wave is prioritised by demand.