Resilience with Resilience4j

David Kumar Jan 2026
2 tabs
package com.example.demo.service;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ResilientService {

    private static final Logger logger = LoggerFactory.getLogger(ResilientService.class);
    private final RestTemplate restTemplate;

    public ResilientService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @CircuitBreaker(name = "externalAPI", fallbackMethod = "fallbackResponse")
    @Retry(name = "externalAPI")
    public String callExternalAPI() {
        logger.info("Calling external API");
        return restTemplate.getForObject("https://api.example.com/data", String.class);
    }

    @RateLimiter(name = "userService")
    public String rateLimitedOperation() {
        logger.info("Executing rate limited operation");
        return "Operation completed";
    }

    @Bulkhead(name = "processingService", type = Bulkhead.Type.THREADPOOL)
    public String isolatedOperation() {
        logger.info("Executing isolated operation");
        // Heavy processing
        return "Processing complete";
    }

    @CircuitBreaker(name = "paymentService", fallbackMethod = "paymentFallback")
    @Retry(name = "paymentService", fallbackMethod = "paymentFallback")
    public String processPayment(String orderId) {
        logger.info("Processing payment for order: {}", orderId);
        // Call payment service
        return "Payment successful";
    }

    // Fallback methods
    private String fallbackResponse(Exception e) {
        logger.error("Fallback triggered due to: {}", e.getMessage());
        return "Service temporarily unavailable. Using cached data.";
    }

    private String paymentFallback(String orderId, Exception e) {
        logger.error("Payment fallback for order {} due to: {}", orderId, e.getMessage());
        return "Payment queued for processing";
    }
}
2 files · java, yaml Explain with highlit

Resilience4j provides resilience patterns for fault tolerance. Circuit breakers prevent cascading failures—open after threshold failures, allow retry after timeout. Rate limiters control request rates. Retry mechanisms handle transient failures. Bulkheads isolate resources preventing exhaustion. Time limiters enforce execution deadlines. Fallback methods provide degraded functionality. I combine patterns for robust microservices. Metrics expose circuit states, failure rates. Spring Boot integration uses annotations—@CircuitBreaker, @RateLimiter, @Retry. Configuration tunes thresholds, timeouts, limits. Resilience4j replaces Netflix Hystrix with lighter, more flexible implementation. Proper resilience design prevents single points of failure and improves system availability under stress.