How To Implement Fault Tolerance In Microservices Using Resilience4j_ - JavaTechOnline
How To Implement Fault Tolerance In Microservices Using Resilience4j_ - JavaTechOnline
- JavaTechOnline
Wednesday, April 23, 2025 Home About Privacy Policy Terms & Conditions Disclaimer Contact Us Guest Post
JavaTechOnline
Making Java Easy To Learn
Table of Contents
1. What is Fault Tolerance in Microservices?
2. Core modules of Resilience4j
3. Common Setup for How to implement Fault Tolerance in Microservices using Resilience4j?
3.1. Create a Spring Boot Project including all dependencies using STS
4. What is Rate Limiting?
5. How to implement Rate Limiting? : Rate Limiting Example
5.1. Step#1: Common Setup for All Examples
5.2. Step#2: Create a RestController class to implement the RateLimiter functionality
5.3. Step#3: Update application.properties
5.4. Step#4: How to test the implemented RateLimiter?
6. What is Retry?
7. How to implement Retry? :Retry Example
7.1. Step#1: Common Setup for All Examples
7.2. Step#2: Create a RestController class to implement the Retry functionality
7.3. Step#3: Update application.properties
7.4. Step#4: How to test the implemented Retry?
8. What is Circuit Breaker ?
8.1. Closed
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 1/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
8.2. Open
8.3. Half-open
9. When to use Circuit Breaker?
10. How to implement Circuit Breaker ? : Circuit Breaker Example
10.1. Step#1: Common Setup for All Examples
10.2. Step#2: Create a RestController class to implement the Circuit Breaker functionality
10.3. Step#3: Update application.properties
11. What is Bulkhead?
12. How to implement Bulkhead ? : Bulkhead Example
12.1. Step#1: Common Setup for All Examples
12.2. Step#2: Create a RestController class to implement the Bulkhead functionality
12.3. Step#3: Update application.properties
13. What is Time Limiting or Timeout Handling?
14. How to implement TimeLimiter ? :TimeLimiter Example
14.1. Step#1: Common Setup for All Examples
14.2. Step#2: Create a RestController class to implement the TimeLimiter functionality
14.3. Step#3: Update application.properties
15. Complete YAML file for all examples
16. How to implement multiple Aspects/patterns in a single method?
17. Conclusion
ADVERTISEMENT
<dependency>
<groupId>org.springframework.boot</groupId>
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 2/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.github.resilience4j.ratelimiter.RequestNotPermitted;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
@RestController
public class RateLimitController {
@GetMapping("/getMessage")
@RateLimiter(name = "getMessageRateLimit", fallbackMethod = "getMessageFallBack")
public ResponseEntity<String> getMessage(@RequestParam(value="name", defaultValue = "Hello") String name){
return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
.body("Too many requests : No further request will be accepted. Please try after sometime");
}
}
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 3/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
resilience4j.ratelimiter.instances.getMessageRateLimit.limit-for-period=2
resilience4j.ratelimiter.instances.getMessageRateLimit.limit-refresh-period=5s
resilience4j.ratelimiter.instances.getMessageRateLimit.timeout-duration=0
The above properties represent that only 2 requests are allowed in 5 seconds duration. Also, there is no timeout duration which means after
completion of 5 seconds, the user can send request again.
2) You should see the result “Message from getMessage() :Hello” on the browser.
3) Now let’s refresh the browser more than 2 times within 5 seconds period.
4) Once you refresh third time within 5 seconds, you should see the message “Too many requests : No further request will be accepted.
Please try after sometime”
5) In console also you should see the logger message as ‘Rate limit has applied, So no further calls are getting accepted’
6) Now update limit-for-period=10 and limit-refresh-period=1s in application.xml. Then, After refreshing the browser multiple times you
should see only success message as “Message from getMessage() :Hello” in the browser.
What is Retry?
Suppose Microservice ‘A’ depends on another Microservice ‘B’. Let’s assume Microservice ‘B’ is a faulty service and its success rate is only
upto 50-60%. However, fault may be due to any reason, such as service is unavailable, buggy service that sometimes responds and
sometimes not, or an intermittent network failure etc. However, in this case, if Microservice ‘A’ retries to send request 2 to 3 times, the
chances of getting response increases. Obviously, we can achieve this functionality with the help of annotation @Retry provided by
Resilience4j without writing a code explicitly.
Here, we have to implement a Retry mechanism in Microservice ‘A’. We will call Microservice ‘A’ as Fault Tolerant as it is participating in
tolerating the fault. However, Retry will take place only on a failure not on a success. By default retry happens 3 times. Moreover, we can
configure how many times to retry as per our requirement.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import io.github.resilience4j.retry.annotation.Retry;
@RestController
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 4/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
public class RetryController {
@GetMapping("/getInvoice")
@Retry(name = "getInvoiceRetry", fallbackMethod = "getInvoiceFallback")
public String getInvoice() {
logger.info("getInvoice() call starts here");
ResponseEntity<String> entity= restTemplate.getForEntity("http://localhost:8080/invoice/rest/find/2", String
logger.info("Response :" + entity.getStatusCode());
return entity.getBody();
}
resilience4j.retry.instances.getInvoiceRetry.max-attempts=5
resilience4j.retry.instances.getInvoiceRetry.wait-duration=2s
resilience4j.retry.instances.getInvoiceRetry.retry-exceptions=org.springframework.web.client.ResourceAccessException
As
aforementioned, By default the retry mechanism makes 3 attempts if the service fails for the first time. But here we have configured for 5
attempts, each after 2 seconds interval. Additionally, if business requires it to retry only if a specific exception occurs, that can also be
configured as above. If we want Resilience4j to retry when any type of exception occurs, we don’t need to mention the property ‘retry-
exceptions’.
3) You should see “getInvoice() call starts here” message 5 times in the console. It means it has tried 5 attempts.
4) Once 5 attempts completes, you should see the message “—RESPONSE FROM FALLBACK METHOD—” in the console. It indicates that the
fallback method called.
5) Subsequently, You will see the “SERVICE IS DOWN, PLEASE TRY AFTER SOMETIME !!!” message in the browser. It indicates that a common
message is getting shown to the user.
6) Now let’s make the called Microservice up. Hit the URl again to see the desired results.
7) If you are getting the desired results successfully, neither Microservice should attempt any retry nor fallback method should be called.
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 5/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
In order to escape the multiple microservices from becoming erroneous as a result of cascading effect, we stop calling the faulty
Microservice ‘B’. Instead, we call a dummy method that is called a ‘Fallback Method’. Therefore, calling a fallback method instead of an
actual service due to a fault is called breaking the circuit. That’s why, we call this as a ‘Circuit Breaker’ Pattern. Moreover, there are generally
three states of a Circuit Breaker Pattern : Closed, Open, Half Open.
Closed
When a Microservice calls the dependent Microservice continuously, then we call the Circuit is in Closed State.
Open
When a MicroService doesn’t call the dependent Microservice, Instead, it calls the fallback method that is implemented to tolerate the fault.
We call this state as Open State. When a certain percentage of requests get failed, let’s say 90%, then we change the state from Closed to
Open.
Half-open
When a Microservice sends a percentage of requests to dependent Microservice and the rest of them to Fallback method. We call this state
as Half-open. During the open state, we can configure the wait duration. Once wait duration is over, the Circuit Breaker will come in Half-
open state. In this state Circuit Breaker checks if the dependent service is up. In order to achieve this, it sends a certain percentage of
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 6/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
requests to dependent service that we can configure. If it gets a positive response from dependent service, it would switch to the closed
state, otherwise it would again go back to the Open State.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
@RestController
public class CircuitBreakerController {
@GetMapping("/getInvoice")
@CircuitBreaker(name = "getInvoiceCB", fallbackMethod = "getInvoiceFallback")
public String getInvoice() {
logger.info("getInvoice() call starts here");
ResponseEntity<String> entity= restTemplate.getForEntity("http://localhost:8080/invoice/rest/find/2", String
logger.info("Response :" + entity.getStatusCode());
return entity.getBody();
}
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 7/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
resilience4j.circuitbreaker.instances.getInvoiceCB.failure-rate-threshold=80
resilience4j.circuitbreaker.instances.getInvoiceCB.sliding-window-size=10
resilience4j.circuitbreaker.instances.getInvoiceCB.sliding-window-type=COUNT_BASED
resilience4j.circuitbreaker.instances.getInvoiceCB.minimum-number-of-calls=5
resilience4j.circuitbreaker.instances.getInvoiceCB.automatic-transition-from-open-to-half-open-enabled=true
resilience4j.circuitbreaker.instances.getInvoiceCB.permitted-number-of-calls-in-half-open-state=4
resilience4j.circuitbreaker.instances.getInvoiceCB.wait-duration-in-open-state=1s
1) ‘failure-rate-threshold=80‘ indicates that if 80% of requests are getting failed, open the circuit ie. Make the Circuit Breaker state as
Open.
2) ‘sliding-window-size=10‘ indicates that if 80% of requests out of 10 (it means 8) are failing, open the circuit.
3) ‘sliding-window-type=COUNT_BASED‘ indicates that we are using COUNT_BASED sliding window. Another type is TIME_BASED.
4) ‘minimum-number-of-calls=5‘ indicates that we need at least 5 calls to calculate the failure rate threshold.
5) ‘automatic-transition-from-open-to-half-open-enabled=true‘ indicates that don’t switch directly from the open state to the closed
state, consider the half-open state also.
6) ‘permitted-number-of-calls-in-half-open-state=4‘ indicates that when on half-open state, consider sending 4 requests. If 80% of them
are failing, switch circuit breaker to open state.
7) ‘wait-duration-in-open-state=1s’ indicates the waiting time interval while switching from the open state to the closed state.
These attributes are the important part of an implementation of a Circuit Breaker. We can configure the values as per our requirement and
test the implemented functionality accordingly.
What is Bulkhead?
In the context of the Fault Tolerance mechanism, if we want to limit the number of concurrent requests, we can use Bulkhead as an aspect.
Using Bulkhead, we can limit the number of concurrent requests within a particular period. Please note the difference between Bulkhead
and Rate Limiting. Rate Limiter never talks about concurrent requests, but Bulkhead does. Rate Limiter talks about limiting number of
requests within a particular period. Hence, using Bulkhead we can limit the number of concurrent requests. We can achieve this
functionality easily with the help of annotation @Bulkhead without writing a specific code.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 8/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
import io.github.resilience4j.ratelimiter.RequestNotPermitted;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
@RestController
public class BulkheadController {
@GetMapping("/getMessage")
@Bulkhead(name = "getMessageBH", fallbackMethod = "getMessageFallBack")
public ResponseEntity<String> getMessage(@RequestParam(value="name", defaultValue = "Hello") String name){
return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
.body("Too many requests : No further request will be accepted. Plese try after sometime");
}
}
resilience4j.bulkhead.instances.getMessageBH.max-concurrent-calls=5
resilience4j.bulkhead.instances.getMessageBH.max-wait-duration=0
‘max-concurrent-calls=5’ indicates that if the number of concurrent calls exceed 5, activate the fallback method.
‘max-wait-duration=0’ indicates that don’t wait for anything, show response immediately based on the configuration.
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 9/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
@RestController
public class TimeLimiterController {
@GetMapping("/getMessageTL")
@TimeLimiter(name = "getMessageTL")
public CompletableFuture<String> getMessage() {
return CompletableFuture.supplyAsync(this::getResponse);
}
resilience4j.timelimiter.instances.getMessageTL.timeout-duration=1ms
resilience4j.timelimiter.instances.getMessageTL.cancel-running-future=false
‘timeout-duration=1ms’ indicates that the maximum amount of time a request can take to respond is 1 millisecond
‘cancel-running-future=false’ indicates that do not cancel the Running Completable Futures After TimeOut.
In order to test the functionality, Run the application as it is. You will get TimeOutException on the Browser. When you change the value of
timeout-duration=1s, you will receive “Executing Within the time Limit…” message in the browser.
resilience4j:
bulkhead:
instances:
getMessageBH:
max-concurrent-calls: 5
max-wait-duration: 0
circuitbreaker:
instances:
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 10/14
4/24/25, 5:20 PM How To Implement Fault Tolerance In Microservices Using Resilience4j? - JavaTechOnline
GetInvoiceCB:
automatic-transition-from-open-to-half-open-enabled: true
failure-rate-threshold: 80
minimum-number-of-calls: 5
permitted-number-of-calls-in-half-open-state: 4
sliding-window-size: 10
sliding-window-type: COUNT_BASED
wait-duration-in-open-state: 10s
ratelimiter:
instances:
getMessageRateLimit:
limit-for-period: 2
limit-refresh-period: 10s
timeout-duration: 0
retry:
instances:
getInvoiceRetry:
enable-exponential-backoff: true
max-attempts: 5
retry-exceptions: org.springframework.web.client.ResourceAccessException
wait-duration: 2s
timelimiter:
instances:
getMessageTL:
cancel-running-future: false
timeout-duration: 1s
1) Bulkhead
2) Time Limiter.
3) Rate Limiter.
4) Circuit Breaker
5) Retry
Moreover, the application.properties file will look like below for the ordering part:
resilience4j.bulkhead.bulkheadAspectOrder =1
resilience4j.timelimiter.timeLimiterAspectOrder =2
resilience4j.ratelimiter.rateLimiterAspectOrder =3
resilience4j.circuitbreaker.circuitBreakerAspectOrder =4
resilience4j.retry.retryAspectOrder =5
Conclusion
After going through all the theoretical & example part of ‘How to implement Fault Tolerance in Microservices using Resilience4j?’, finally, we
should be able to integrate Resilience4j with the Microservices. Similarly, we expect from you to further extend these examples and
implement them in your project accordingly. I hope you might be convinced by the article ‘How to implement Fault Tolerance in
Microservices using Resilience4j?’. In addition, If there is any update in the future, we will also update the article accordingly. Moreover, Feel
free to provide your comments in the comments section below.
https://javatechonline.com/fault-tolerance-in-microservices-resilience4j-spring-boot/ 11/14