Graceful Degradation
Definition

Degradation Strategies

Implementation Examples
// Pattern 1: Fallback with Circuit Breaker
@Service
public class ProductService {
@CircuitBreaker(name = "recommendations", fallbackMethod = "fallbackRecommendations")
public List<Product> getRecommendations(String userId) {
return recommendationClient.getRecommendations(userId);
}
// Fallback when recommendation service is down
public List<Product> fallbackRecommendations(String userId, Exception e) {
log.warn("Recommendation service unavailable, using fallback", e);
// Try cached recommendations
List<Product> cached = cache.get("recommendations:" + userId);
if (cached != null) {
return cached;
}
// Return popular products as default
return productRepository.findTopByOrderBySalesDesc(10);
}
}
// Pattern 2: Feature Toggle on Failure
@Service
public class SearchService {
private final AtomicBoolean advancedSearchEnabled = new AtomicBoolean(true);
public SearchResults search(SearchQuery query) {
if (advancedSearchEnabled.get()) {
try {
return elasticSearch.search(query);
} catch (ElasticSearchException e) {
advancedSearchEnabled.set(false); // Disable feature
scheduleRetry(); // Try to re-enable later
log.error("Advanced search failed, degrading to basic", e);
}
}
// Degraded: basic database search
return basicDatabaseSearch(query);
}
private void scheduleRetry() {
scheduler.schedule(() -> {
try {
elasticSearch.healthCheck();
advancedSearchEnabled.set(true);
log.info("Advanced search re-enabled");
} catch (Exception e) {
scheduleRetry(); // Keep trying
}
}, 30, TimeUnit.SECONDS);
}
}
Tiered Degradation

Resilience Patterns
// Circuit Breaker Pattern
@Configuration
public class ResilienceConfig {
@Bean
public CircuitBreakerConfig circuitBreakerConfig() {
return CircuitBreakerConfig.custom()
.failureRateThreshold(50) // Open at 50% failure rate
.waitDurationInOpenState(Duration.ofSeconds(30))
.slidingWindowSize(10)
.build();
}
}
// Bulkhead Pattern - Isolate failures
@Service
public class OrderService {
@Bulkhead(name = "inventory", type = Bulkhead.Type.THREADPOOL)
public StockResult checkInventory(String productId) {
return inventoryClient.check(productId);
}
@Bulkhead(name = "payment", type = Bulkhead.Type.THREADPOOL)
public PaymentResult processPayment(PaymentRequest request) {
return paymentClient.process(request);
}
// Inventory issues don't affect payment processing
// Each has its own thread pool
}
// Timeout with Fallback
@Service
public class PricingService {
@TimeLimiter(name = "pricing", fallbackMethod = "fallbackPrice")
public CompletableFuture<Price> getDynamicPrice(String productId) {
return CompletableFuture.supplyAsync(() ->
pricingEngine.calculate(productId)
);
}
public CompletableFuture<Price> fallbackPrice(String productId, Exception e) {
// Return list price when dynamic pricing times out
return CompletableFuture.completedFuture(
productRepository.getListPrice(productId)
);
}
}
Caching for Degradation
// Cache-aside with stale data fallback
@Service
public class ContentService {
private final Cache<String, Content> cache;
private final Cache<String, Content> staleCache; // Longer TTL
public Content getContent(String contentId) {
// Try fresh cache
Content cached = cache.getIfPresent(contentId);
if (cached != null) {
return cached;
}
try {
// Fetch from source
Content fresh = contentApi.fetch(contentId);
cache.put(contentId, fresh);
staleCache.put(contentId, fresh); // Also update stale cache
return fresh;
} catch (Exception e) {
log.warn("Content fetch failed, trying stale cache", e);
// Fallback to stale data
Content stale = staleCache.getIfPresent(contentId);
if (stale != null) {
return stale.withStaleWarning();
}
throw new ContentUnavailableException(contentId, e);
}
}
}
// Response indicating degraded state
public class ApiResponse<T> {
private T data;
private boolean degraded;
private String degradedReason;
private Instant dataAsOf; // When data was fetched
public static <T> ApiResponse<T> degraded(T fallbackData, String reason) {
return new ApiResponse<>(fallbackData, true, reason, Instant.now());
}
}
Frontend Degradation

Tips & Tricks
