Originally published at claudeguide.io/claude-api-model-fallback-resilience
Claude API Model Fallback & Circuit Breaker: Production Resilience (2026)
Anthropic's API has 99.9% uptime but real-world disruption is more frequent — 429 rate limits, 529 overloaded responses, model-specific outages, transient network errors. Production agents need 5 resilience patterns: model fallback (Sonnet → Haiku → cached response), circuit breaker (stop hammering a failing endpoint), exponential backoff with jitter, bulkhead isolation (rate limits per feature), and graceful degradation paths. Without these, a 5-minute Anthropic blip becomes a 5-hour customer-facing outage. This guide is patterns from 12 production retrospectives — what worked, what didn't.
For Claude API basics see Rate Limits & 429 Recovery. For error handling fundamentals see Claude API Error Handling.
The 5 Patterns at a Glance
| Pattern | Prevents | Cost |
|---|---|---|
| Model fallback | Single-model outage | Quality drop on fallback |
| Circuit breaker | Cascading failure | 30-60s blackout window |
| Exp backoff + jitter | Thundering herd | Latency spike during retry |
| Bulkhead | Feature A killing feature B | Lower effective rate limit |
| Graceful degradation | Total feature loss | Reduced functionality |
Pattern 1: Model Fallback Chain
Sonnet down? Fall to Haiku. Haiku down? Fall to cached response. Always have an answer.
import anthropic
from anthropic import APIError
FALLBACK_CHAIN = [
{"model": "claude-sonnet-4-5", "max_tokens": 1024},
{"model": "claude-haiku-3-5", "max_tokens": 1024},
]
async def call_with_fallback(messages, system=None):
for i, config in enumerate(FALLBACK_CHAIN):
try:
return await client.messages.create(
**config,
system=system,
messages=messages,
timeout=15
)
except APIError as e:
if e.status_code in (429, 500, 502, 503, 529):
logger.warning(f"Model {config['model']} failed: {e}; trying next")
continue
raise
except TimeoutError:
logger.warning(f"Model {config['model']} timed out")
continue
# All models failed — return cached or canned response
return get_cached_response(messages) or {
"content": [{"text": "Service temporarily unavailable. Please retry."}]
}
Quality trade-off: Haiku is 70-85% as capable as Sonnet for most tasks. Fallback degrades quality, not features. Document this in your SLA. See Haiku vs Sonnet vs Opus for capability comparison.
Pattern 2: Circuit Breaker
Stop pounding on a failing service. After N failures, open the circuit and skip calls for a cooldown period.
python
import time
from enum import Enum
class CircuitState(Enum):
CLOSED = "closed" # Normal — requests pass through
OPEN = "open" # Failures — block requests
HALF_OPEN = "half_open" # Probing — allow one request
class CircuitBreaker:
def __init__(self, failure_threshold=5, cooldown=60):
self.state = CircuitState.CLOSED
self.failure_count = 0
self.last_failure_time = 0
self.failure_threshold = failure_threshold
self.cooldown = cooldown
def can_attempt(self) -
Top comments (0)