Skip to content
Learni
View all tutorials
Développement Java

How to Integrate Resilience4j with Spring Boot in 2026

Lire en français

Introduction

Resilience4j is a lightweight, modular library that implements essential resilience patterns for distributed applications. In a microservices ecosystem, network calls can fail at any time. With mechanisms like circuit breaker, retry, or bulkhead, Resilience4j makes your application more robust without adding unnecessary complexity. This tutorial guides you step by step through integrating it into Spring Boot, from installation to practical use of two major patterns.

Prerequisites

  • Java 17 or higher
  • Spring Boot 3.2+
  • Maven or Gradle
  • Basic knowledge of Spring Boot and REST

Add the Maven Dependency

pom.xml
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot3</artifactId>
    <version>2.2.0</version>
</dependency>

This dependency enables native Resilience4j integration with Spring Boot 3. It automatically includes annotations and configuration via application.yml.

Basic Configuration

Create an application.yml file to define your patterns. Each pattern has its own identifier and can be enabled independently.

Configure Circuit Breaker and Retry

src/main/resources/application.yml
resilience4j:
  circuitbreaker:
    instances:
      paymentService:
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 30s
        permittedNumberOfCallsInHalfOpenState: 3
  retry:
    instances:
      paymentService:
        maxAttempts: 3
        waitDuration: 500ms

This file configures a circuit breaker that opens after 50% failures over 10 calls and a retry mechanism with 3 attempts spaced 500 ms apart.

Create the Service with Annotations

PaymentService.java
package com.example.demo.service;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.stereotype.Service;

@Service
public class PaymentService {

    @CircuitBreaker(name = "paymentService", fallbackMethod = "fallbackPayment")
    @Retry(name = "paymentService")
    public String processPayment(String orderId) {
        // Simulate an external call
        if (Math.random() < 0.7) {
            throw new RuntimeException("Service indisponible");
        }
        return "Paiement validé pour " + orderId;
    }

    public String fallbackPayment(String orderId, Exception ex) {
        return "Paiement différé - mode dégradé pour " + orderId;
    }
}

The @CircuitBreaker and @Retry annotations are applied directly to the method. The fallbackMethod is automatically invoked when the circuit is open.

Expose via a REST Controller

PaymentController.java
package com.example.demo.controller;

import com.example.demo.service.PaymentService;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/payments")
public class PaymentController {

    private final PaymentService paymentService;

    public PaymentController(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    @GetMapping("/{orderId}")
    public String pay(@PathVariable String orderId) {
        return paymentService.processPayment(orderId);
    }
}

The controller simply calls the service. All resilience logic is handled by Resilience4j with no additional code required.

Start and Test the Application

terminal
./mvnw spring-boot:run

Start the application then call http://localhost:8080/payments/123 multiple times to observe the circuit breaker opening and the fallback activating.

Best Practices

  • Name your instances descriptively (e.g., paymentService rather than cb1)
  • Always define a relevant fallbackMethod
  • Monitor metrics via Actuator and Prometheus
  • Test failure scenarios in a staging environment
  • Start with conservative thresholds then adjust based on observations

Common Mistakes to Avoid

  • Forgetting to enable the @EnableCircuitBreaker annotation (unnecessary with Spring Boot 3)
  • Using the same instance name for different services
  • Not handling exceptions in the fallback
  • Configuring overly aggressive thresholds from the start

Going Further

Discover our advanced training on distributed systems resilience: https://learni-group.com/formations