- Java Microservices Tutorial
- Java Microservices - Home
- Microservices - Introduction
- Microservices vs Monolith vs SOA
- Java Microservices - Environment Setup
- Java Microservices - Advantages of Spring Boot
- Java Microservices - Design Patterns
- Java Microservices - Domain Driven Design
- Java Microservices - Decomposition by Business Capability
- Java Microservices - Decomposition by Subdomain
- Java Microservices - Backend for Frontend
- Java Microservices - The Strangler Pattern
- Java Microservices - Synchronous Communication
- Java Microservices - Asynchronous Communication
- Java Microservices - Saga Pattern
- Java Microservices - Centralized Logging (ELK Stack)
- Java Microservices - Event Sourcing
- Java Microservices - CQRS Pattern
- Java Microservices - Sidecar Pattern
- Java Microservices - Service Mesh Pattern
- Java Microservices - Circuit Breaker Pattern
- Java Microservices - Distributed Tracing
- Java Microservices - Control Loop Pattern
- Java Microservices - Database Per Service
- Java Microservices - Bulkhead Pattern
- Java Microservices - Health Check API
- Java Microservices - Retry Pattern
- Java Microservices - Fallback Pattern
- Java Microservices Useful Resources
- Java Microservices Quick Guide
- Java Microservices Useful Resources
- Java Microservices Discussion
Java Microservices - Fallback Pattern
Introduction
In modern distributed systems like microservices architectures, remote calls between services are common. Unfortunately, these calls are prone to failure, latency due to various reasons like −
Network glitches
Service overload
Infrastructure failures
Dependency crashes
In such situations, failing fast or displaying an error is not always the best user experience. This is where the Fallback Pattern comes into play − it helps ensure graceful degradation by providing a default or alternative response when the primary service fails.
Motivation and Problem Statement
Let's imagine a simple e-commerce platform with the following services −
ProductService
InventoryService
RecommendationService
Suppose RecommendationService is down. If a customer tries to view a product, and this service doesn't respond, the user experience degrades. However, the core functionality − viewing the product − should not fail just because one non-critical component failed.
Problems Without Fallback
Entire service or API fails because a dependent service is unavailable.
Poor customer experience due to error pages.
Increased support tickets/user dissatisfaction.
Solution− Fallback
Instead of erroring out, we can provide −
Partial or best-effort responses
Static default recommendations
"Service temporarily unavailable" messages
What Is the Fallback Pattern?
The Fallback Pattern is a resiliency pattern in which a microservice automatically provides an alternative response or takes corrective action when a primary operation fails.
When and Where to Use the Fallback Pattern
Suitable Scenarios
Optional features like recommendations, personalization, or analytics
Dependency on third-party APIs
Known unstable services
Circuit breaker trips
Avoid Using When
The fallback data is misleading or risky (e.g., financial transactions)
No safe default or alternative is available
The operation is business-critical and must be retried or alerted
Fallback Pattern in Action
Imagine the following interaction −
Client → ProductService → InventoryService (Fails)
|- Fallback: Show "Inventory info not available"
Example Responses
"We're experiencing delays, please try again later."
"Recommendations are temporarily unavailable."
This keeps the user interface functional even during failures.
Design Considerations
While implementing a fallback, keep in mind−
Is the fallback accurate and safe to use?
Is the fallback temporary or a long-term solution?
Should fallback responses be logged or alerted?
How does fallback behavior affect system stability?
Real-World Use Cases
Streaming Platforms
Show default thumbnails when video metadata service is slow.
Display cached user watch history.
E-commerce
Fallback to default product recommendations when product-recommendation service is down.
Use cached stock levels when inventory service fails.
Mobile Applications
Offline fallback UI when network is unavailable
Cached results from previous sessions
Implementation − Spring Boot + Resilience4j
Step 1: Add Dependencies
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot3</artifactId> <version>2.0.2</version> </dependency>
Step 2: Create a Service with Fallback
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
@Service
public class RecommendationService {
@CircuitBreaker(name = "recommendationCB", fallbackMethod = "fallbackRecommendations")
public List<String> getRecommendations(String userId) {
// Simulate API call
if (Math.random() > 0.5) {
throw new RuntimeException("Service Down");
}
return List.of("Book1", "Book2");
}
public List<String> fallbackRecommendations(String userId, Throwable t) {
// Default fallback
return List.of("Top Sellers", "Trending Now");
}
}
Configuration (Optional) ( snippet of 'application.yml')
resilience4j.circuitbreaker:
instances:
recommendationCB:
registerHealthIndicator: true
slidingWindowSize: 5
failureRateThreshold: 50
Common Mistakes and Challenges
Poor Fallback Choices
Returning misleading or outdated fallback data can break the business logic or user trust.
Overuse of Fallbacks
Fallbacks are not a substitute for fixing actual issues. Overusing them can hide systemic problems.
Lack of Monitoring
Not tracking fallback usage may lead to undetected outages.
Not Testing Fallbacks
Fallbacks need to be tested regularly under failure scenarios.
Best Practices
Design fallbacks that maintain business value without compromising data integrity.
Log fallback triggers for monitoring and alerting.
Make fallback responses idempotent and safe.
Use circuit breakers in combination to reduce load on failing services.
Tools and Frameworks
| Sr.No. | Tool | Usage |
|---|---|---|
| 1 | Resilience4j | Circuit breaker, fallback, retry, rate limiter |
| 2 | Spring Cloud Circuit Breaker | Abstraction layer for various fallback tools |
| 3 | Failsafe (Java) | Lightweight fault tolerance library |
| 4 | Polly (.NET) | Retry and fallback handling in .NET |
| 5 | Istio / Service Mesh | Fallbacks at the network layer via routing rules |
Conclusion
The Fallback Pattern is a critical tool in the microservices developer's toolbox. It helps services maintain partial functionality in the face of failure and enhances user experience, system resilience, and fault isolation.
By thoughtfully designing and testing fallback responses, developers can ensure graceful degradation and protect their systems from cascading failures.