You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reqwest added retry policies in #2763, which is great. The next layer up — circuit breaking — still doesn't exist. The two patterns are complementary but distinct:
Retry: "this request failed, try again"
Circuit breaker: "this backend has been failing for 30 seconds, stop sending requests entirely until it recovers"
Without a circuit breaker, retry policies can make outages worse: every client keeps hammering a downed backend, retry storms pile up, and connection pools exhaust. The circuit breaker cuts this off at the source.
What this would look like
A ClientBuilder::circuit_breaker() method accepting a CircuitBreakerConfig, similar to how .retry() works:
let client = reqwest::Client::builder().retry(RetryPolicy::default()).circuit_breaker(CircuitBreakerConfig::new().failure_threshold(5)// open after 5 failures.success_threshold(0.8)// close when 80 % of probes succeed.timeout(Duration::from_secs(30))// probe after 30 s).build()?;
The three-state machine (Closed → Open → HalfOpen) is well understood. The key implementation choices:
Scope: per-Client instance (same base URL shares one breaker) or per-hostname? Per-hostname is more useful for multi-host clients.
Error classification: HTTP 5xx and connection errors trip the breaker; 4xx do not.
Retry-After header (issue Support Retry-After header #925): circuit breaker timeout could respect this header automatically.
Prior art in the Tokio ecosystem
I recently submitted tower-rs/tower#855 adding a CircuitBreaker Tower middleware. The implementation there is a Service<Request> wrapper — the same pattern could be adapted as a reqwest middleware layer or built into the client directly.
The full implementation with tests is available at that PR if it's useful as a reference.
Happy to implement this for reqwest if there's appetite — wanted to check the preferred API shape first.
The gap
reqwestadded retry policies in #2763, which is great. The next layer up — circuit breaking — still doesn't exist. The two patterns are complementary but distinct:Without a circuit breaker, retry policies can make outages worse: every client keeps hammering a downed backend, retry storms pile up, and connection pools exhaust. The circuit breaker cuts this off at the source.
What this would look like
A
ClientBuilder::circuit_breaker()method accepting aCircuitBreakerConfig, similar to how.retry()works:The three-state machine (Closed → Open → HalfOpen) is well understood. The key implementation choices:
Clientinstance (same base URL shares one breaker) or per-hostname? Per-hostname is more useful for multi-host clients.Retry-Afterheader (issue Support Retry-After header #925): circuit breaker timeout could respect this header automatically.Prior art in the Tokio ecosystem
I recently submitted tower-rs/tower#855 adding a
CircuitBreakerTower middleware. The implementation there is aService<Request>wrapper — the same pattern could be adapted as areqwestmiddleware layer or built into the client directly.The full implementation with tests is available at that PR if it's useful as a reference.
Happy to implement this for
reqwestif there's appetite — wanted to check the preferred API shape first.— Matthew Busel