python.resilience.missing_circuit_breaker
Stability
High
Detects HTTP client calls to external services without circuit breaker protection, which can cause cascading failures.
Why It Matters
Section titled “Why It Matters”Without circuit breakers, a failing dependency can:
- Cause cascading failures — Slow downstream services cause your service to slow down
- Exhaust resources — Threads/connections pile up waiting for unresponsive services
- Extend outages — Continuous retries prevent the failing service from recovering
- Affect all users — One bad dependency impacts all requests
Circuit breakers “trip” after consecutive failures, failing fast without hitting the troubled service.
Example
Section titled “Example”# ❌ Before (no circuit breaker)def fetch_data(): return requests.get('https://api.example.com/data', timeout=30)# ✅ After (with circuit breaker)from circuitbreaker import circuit
@circuit(failure_threshold=5, recovery_timeout=60)def fetch_data(): # After 5 consecutive failures, circuit opens for 60 seconds # During this time, calls fail fast without hitting the external service return requests.get('https://api.example.com/data', timeout=30)What Unfault Detects
Section titled “What Unfault Detects”- HTTP calls (
requests,httpx,aiohttp) without circuit breaker decorators - gRPC client calls without circuit protection
- External service integrations without failure isolation
Auto-Fix
Section titled “Auto-Fix”Unfault generates patches that add circuit breaker decorators using the circuitbreaker library:
from circuitbreaker import circuit
@circuit(failure_threshold=5, recovery_timeout=60)def fetch_external_data(): response = requests.get('https://api.example.com/data', timeout=30) return response.json()Configuration Options
Section titled “Configuration Options”# Using pybreaker for more controlfrom pybreaker import CircuitBreaker, CircuitBreakerListener
class LoggingListener(CircuitBreakerListener): def state_change(self, cb, old_state, new_state): logger.warning(f"Circuit {cb.name}: {old_state} -> {new_state}")
breaker = CircuitBreaker( fail_max=5, reset_timeout=60, listeners=[LoggingListener()])
@breakerdef fetch_data(): return requests.get('https://api.example.com/data', timeout=30)