DEV Community

Sangmin Lee
Sangmin Lee

Posted on • Originally published at claudeguide.io

Claude API Model Fallback & Circuit Breaker: Production Resilience (2026)

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."}]
    }
Enter fullscreen mode Exit fullscreen mode

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) -
Enter fullscreen mode Exit fullscreen mode

Top comments (0)