Implementing Resilient Microservices with Resilience4j

Arvind Kumar
2 min readJan 5, 2025

--

Microservices depend on multiple downstream systems, making them prone to failures like timeouts, slow responses, or service unavailability. Resilience4j provides tools to handle these gracefully, ensuring reliability.

In this post, we’ll implement Resilience4j with Spring Boot 3.x, using WebClient for non-blocking HTTP requests.

Problem Statement

Consider a CurrencyService that fetches exchange rates from an external API. If the API is unresponsive or slow, it can affect the entire service. Our goal is to handle such failures using Resilience4j with a Circuit Breaker, Retry, and Fallback mechanisms.

Gradle Setup

Add the following dependencies to your build.gradle:

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.x.x'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-aop'
}

Configuration

Update application.yml for Resilience4j configuration:

resilience4j:
circuitbreaker:
instances:
currencyService:
failure-rate-threshold: 50
wait-duration-in-open-state: 10s
permitted-number-of-calls-in-half-open-state: 2
sliding-window-size: 10
retry:
instances:
currencyService:
max-attempts: 3
wait-duration: 2s
timelimiter:
instances:
currencyService:
timeout-duration: 3s

Service with WebClient

Here’s how to use WebClient with Resilience4j:

import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
@Service
public class CurrencyService {
private final WebClient webClient;
public CurrencyService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://api.exchangerate-api.com/v4/latest").build();
}
@CircuitBreaker(name = "currencyService", fallbackMethod = "fallbackForCurrencyService")
@Retry(name = "currencyService")
public String getExchangeRates(String currency) {
return webClient.get()
.uri("/{currency}", currency)
.retrieve()
.bodyToMono(String.class)
.block();
}
public String fallbackForCurrencyService(String currency, Throwable throwable) {
return "Fallback response for " + currency + ": { 'USD': 1, 'EUR': 0.85 }";
}
}

Controller

Expose an API to test the service:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CurrencyController {
private final CurrencyService currencyService;
public CurrencyController(CurrencyService currencyService) {
this.currencyService = currencyService;
}
@GetMapping("/api/rates/{currency}")
public String getExchangeRates(@PathVariable String currency) {
return currencyService.getExchangeRates(currency);
}
}

Flow of requests

https://github.com/codefarm0/SpringBoot

**Note — source code for the above diagram — link

Monitoring Circuit States

  • Enable Actuator Add the following to application.yml:
management:
endpoints:
web:
exposure:
include: health, metrics, resilience4j.circuitbreaker
  • Monitor Metrics Access circuit breaker metrics via actuator at /actuator/metrics/resilience4j.circuitbreaker.
  • Detailed Insights For more details, you can enable Resilience4j’s Prometheus or Micrometer integration for visualization using tools like Grafana.

Simulate Failures

Modify the baseUrl in CurrencyService to an invalid URL. Observe:

  • Retry: Attempts to fetch data multiple times.
  • Circuit Breaker: Tracks failures and transitions to Open state.
  • Fallback: Returns a default response when the circuit is open.

Conclusion

Resilience4j ensures your microservices remain resilient under adverse conditions. Combining Circuit Breaker, Retry, and Fallback provides robust fault tolerance.

With Spring Boot 3.x and WebClient, you can build non-blocking, fault-tolerant APIs ready for modern distributed architectures. Would you like additional insights into Prometheus integration or advanced configuration?

— — — — —

Let me know your thoughts/feedback in the comment section. Clap this story if found useful and follow me for more such content.

--

--

Arvind Kumar
Arvind Kumar

Written by Arvind Kumar

Staff Engineer @Chegg || Passionate about technology || https://youtube.com/@codefarm0

No responses yet