What you'll learn: By the end of this guide you will be able to implement circuit breakers and fallback chains for LLM calls, design graceful degradation UX patterns, apply bulkhead isolation between AI components, and test failure modes systematically before they hit production.
LLM providers have outages. OpenAI's status page shows multiple incidents per quarter. Anthropic, Groq, and every other provider have the same pattern. The question is not whether your LLM dependency will fail — it is whether your system handles that failure gracefully or cascades into a full outage.
The patterns in this guide come from operating AI systems that serve production traffic 24/7 with a 99.9% uptime SLA.
The Resilience Stack
Circuit Breakers for LLM Calls
A circuit breaker stops calling a failing dependency for a defined period, preventing cascade failures and allowing the downstream service to recover.
@Service
public class ResilientLLMService {
private final ChatClient primaryClient; // GPT-4o
private final ChatClient fallbackClient; // GPT-4o-mini
// Circuit breaker: opens after 5 failures in 10s, tries again after 30s
@CircuitBreaker(
name = "openai-primary",
fallbackMethod = "fallbackAnswer"
)
@Retry(name = "openai-retry") // 3 retries with exponential backoff
@TimeLimiter(name = "openai-timeout") // 8 second hard timeout
public CompletableFuture<String> answer(String question) {
return CompletableFuture.supplyAsync(() ->
primaryClient.prompt()
.user(question)
.call()
.content()
);
}
// Automatically called when circuit is open or retries exhausted
public CompletableFuture<String> fallbackAnswer(String question, Exception ex) {
log.warn("Primary LLM unavailable ({}), using fallback", ex.getClass().getSimpleName());
return CompletableFuture.supplyAsync(() ->
fallbackClient.prompt()
.user(question)
.call()
.content()
);
}
}
Resilience4j configuration:
resilience4j:
circuitbreaker:
instances:
openai-primary:
slidingWindowSize: 10
failureRateThreshold: 50 # Open after 50% failures in window
waitDurationInOpenState: 30s # Wait 30s before half-open
permittedNumberOfCallsInHalfOpenState: 3
retry:
instances:
openai-retry:
maxAttempts: 3
waitDuration: 1s
enableExponentialBackoff: true
exponentialBackoffMultiplier: 2
retryExceptions:
- java.io.IOException
- org.springframework.web.client.ResourceAccessException
timelimiter:
instances:
openai-timeout:
timeoutDuration: 8s
Fallback Chain Design
Design your fallback chain based on cost/quality trade-offs: