| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| title | Fallback Pattern in Java: Graceful Degradation in Microservices | |||
|---|---|---|---|---|
| shortTitle | Fallback | |||
| description | Learn about the Fallback pattern in Java design, which ensures microservice resilience and graceful system degradation when primary dependencies fail. | |||
| category | Resilience | |||
| language | en | |||
| tag |
|
The Fallback design pattern is a resiliency pattern used in microservices architecture to handle failures gracefully. It ensures that when a service is unavailable, fails, or times out, the system can continue to operate by providing an alternative response or executing a predefined fallback mechanism. This pattern enhances robustness and reliability by preventing cascading failures and improving the overall user experience.
Real-world example
Consider a movie streaming application like Netflix. The home page loads personalized recommendations for the logged-in user. If the recommendation microservice goes offline or is too slow, the user shouldn't see a broken page. Instead, the system falls back to a cached list of globally popular movies. While the response is degraded (not personalized), the application remains functional, providing a seamless user experience.
In plain words
Fallback ensures that if a primary service call fails, the application falls back to a backup strategy (e.g. cached response, default value, or simplified service) rather than raising an error and failing completely.
Wikipedia says
A fallback is a contingency option to be taken if the preferred choice is unavailable. In software, fallback mechanisms are crucial for fault tolerance, allowing systems to degrade gracefully rather than crash.
This Java example demonstrates how the Fallback pattern can manage service failures, integrate with a Circuit Breaker, and apply timeout limits.
Defining the Remote Service Interface
The RemoteService interface represents any external dependency call.
public interface RemoteService {
String execute() throws Exception;
}Defining the Primary Service and Fallback Service
The PrimaryService simulates our main external dependency which may suffer from errors or latency. The FallbackService returns a cached or degraded static response.
// Primary Service simulating latency and errors
var healthyPrimary = new PrimaryService("Healthy data from primary service", 10, false);
var failingPrimary = new PrimaryService("Failing service", 0, true);
var slowPrimary = new PrimaryService("Slow response from primary service", 500, false);
// Fallback Service providing degraded response
var fallback = new FallbackService("Fallback degraded/cached response");Monitoring Health with a Circuit Breaker
A SimpleCircuitBreaker tracks the number of failures to trip the circuit to OPEN, bypassing the primary service immediately to avoid waiting for timeouts.
// Trip after 2 failures; retry after 1 second
var circuitBreaker = new SimpleCircuitBreaker(2, 1000);Executing Calls with the FallbackExecutor
The FallbackExecutor uses virtual threads to execute the primary service call. It applies timeouts, handles exceptions, records failures to the circuit breaker, and falls back to the fallback service as needed.
try (var executor = new FallbackExecutor()) {
// Scenario 1: Healthy primary service call
String response1 = executor.execute(healthyPrimary, fallback, circuitBreaker, 100);
LOGGER.info("Response: {}", response1); // Healthy data from primary service
// Scenario 2: Failing service call triggers fallback
String response2 = executor.execute(failingPrimary, fallback, circuitBreaker, 100);
LOGGER.info("Response: {}", response2); // Fallback degraded/cached response
}The Fallback pattern is applicable:
Benefits:
Trade-Offs:
| Back | FazBrowse Home | New Git URL |