SkillAgentSearch skills...

Resilience4j

Resilience4j is a fault tolerance library designed for Java8 and functional programming

Install / Use

/learn @resilience4j/Resilience4j
About this skill

Quality Score

0/100

Category

Design

Supported Platforms

Universal

README

= Fault tolerance library designed for functional programming :author: Robert Winkler and Bohdan Storozhuk :icons: :toc: macro :numbered: 1 ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: :important-caption: :heavy_exclamation_mark: :caution-caption: :fire: :warning-caption: :warning: endif::[]

image:https://github.com/resilience4j/resilience4j/actions/workflows/gradle-build.yml/badge.svg["Build Status"] image:https://img.shields.io/nexus/r/io.github.resilience4j/resilience4j-circuitbreaker?server=https%3A%2F%2Foss.sonatype.org["Release"] image:https://img.shields.io/nexus/s/io.github.resilience4j/resilience4j-circuitbreaker?server=https%3A%2F%2Foss.sonatype.org["Snapshot"] image:http://img.shields.io/badge/license-ASF2-blue.svg["Apache License 2", link="http://www.apache.org/licenses/LICENSE-2.0.txt"]

image:https://sonarcloud.io/api/project_badges/measure?project=resilience4j_resilience4j&metric=coverage["Coverage", link="https://sonarcloud.io/dashboard?id=resilience4j_resilience4j"] image:https://sonarcloud.io/api/project_badges/measure?project=resilience4j_resilience4j&metric=sqale_rating["Maintainability", link="https://sonarcloud.io/dashboard?id=resilience4j_resilience4j"] image:https://sonarcloud.io/api/project_badges/measure?project=resilience4j_resilience4j&metric=reliability_rating["Reliability", link="https://sonarcloud.io/dashboard?id=resilience4j_resilience4j"] image:https://sonarcloud.io/api/project_badges/measure?project=resilience4j_resilience4j&metric=security_rating["Security", link="https://sonarcloud.io/dashboard?id=resilience4j_resilience4j"] image:https://sonarcloud.io/api/project_badges/measure?project=resilience4j_resilience4j&metric=vulnerabilities["Vulnerabilities", link="https://sonarcloud.io/dashboard?id=resilience4j_resilience4j"] image:https://sonarcloud.io/api/project_badges/measure?project=resilience4j_resilience4j&metric=bugs["Bugs", link="https://sonarcloud.io/dashboard?id=resilience4j_resilience4j"]

image:https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg["SWUbanner",link="https://vshymanskyy.github.io/StandWithUkraine"]

toc::[]

== Introduction

Resilience4j is a lightweight fault tolerance library designed for functional programming. Resilience4j provides higher-order functions (decorators) to enhance any functional interface, lambda expression or method reference with a Circuit Breaker, Rate Limiter, Retry or Bulkhead. You can stack more than one decorator on any functional interface, lambda expression or method reference. The advantage is that you have the choice to select the decorators you need and nothing else.

Resilience4j 3 requires Java 21.

[source,java]

// Create a CircuitBreaker with default configuration CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("backendService");

// Create a Retry with default configuration // 3 retry attempts and a fixed time interval between retries of 500ms Retry retry = Retry.ofDefaults("backendService");

// Create a Bulkhead with default configuration Bulkhead bulkhead = Bulkhead.ofDefaults("backendService");

Supplier<String> supplier = () -> backendService .doSomething(param1, param2);

// Decorate your call to backendService.doSomething() // with a Bulkhead, CircuitBreaker and Retry // **note: you will need the resilience4j-all dependency for this Supplier<String> decoratedSupplier = Decorators.ofSupplier(supplier) .withCircuitBreaker(circuitBreaker) .withBulkhead(bulkhead) .withRetry(retry) .decorate();

// Execute the decorated supplier and recover from any exception String result = Try.ofSupplier(decoratedSupplier) .recover(throwable -> "Hello from Recovery").get();

// When you don't want to decorate your lambda expression, // but just execute it and protect the call by a CircuitBreaker. String result = circuitBreaker .executeSupplier(backendService::doSomething);

// You can also run the supplier asynchronously in a ThreadPoolBulkhead ThreadPoolBulkhead threadPoolBulkhead = ThreadPoolBulkhead .ofDefaults("backendService");

// The Scheduler is needed to schedule a timeout on a non-blocking CompletableFuture ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3); TimeLimiter timeLimiter = TimeLimiter.of(Duration.ofSeconds(1));

CompletableFuture<String> future = Decorators.ofSupplier(supplier) .withThreadPoolBulkhead(threadPoolBulkhead) .withTimeLimiter(timeLimiter, scheduler) .withCircuitBreaker(circuitBreaker) .withFallback(asList(TimeoutException.class, CallNotPermittedException.class, BulkheadFullException.class), throwable -> "Hello from Recovery") .get().toCompletableFuture();

NOTE: With Resilience4j you don’t have to go all-in, you can https://mvnrepository.com/artifact/io.github.resilience4j[pick what you need].

== Documentation

Setup and usage is described in our https://resilience4j.readme.io/docs[User Guide].

  • https://github.com/resilience4j-docs-ja/resilience4j-docs-ja[有志による日本語訳(非公式) Japanese translation by volunteers(Unofficial)]

  • https://github.com/lmhmhl/Resilience4j-Guides-Chinese[这是Resilience4j的非官方中文文档 Chinese translation by volunteers(Unofficial)]

== Overview

Resilience4j provides several core modules:

  • resilience4j-circuitbreaker: Circuit breaking
  • resilience4j-ratelimiter: Rate limiting
  • resilience4j-bulkhead: Bulkheading
  • resilience4j-retry: Automatic retrying (sync and async)
  • resilience4j-timelimiter: Timeout handling
  • resilience4j-cache: Result caching

There are also add-on modules for metrics, Feign, Kotlin, Spring, Ratpack, Vertx, RxJava2 and more.

NOTE: Find out full list of modules in our https://resilience4j.readme.io/docs#section-modularization[User Guide].

TIP: For core modules package or +Decorators+ builder see https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-all[resilience4j-all].

== Best Practices

=== Instance Management: When to Share vs. Not Share Instances

One of the most important concepts for newcomers to understand is when to create separate instances versus when to share instances across different remote services or backends.

[IMPORTANT]

The Golden Rule: Create a unique instance (with a unique ID) for each protected remote service or backend you communicate with.

==== Why Unique Instances Matter

Creating separate instances for each backend service is critical for:

  1. Proper metrics collection - Each instance tracks its own metrics, allowing you to monitor the health of individual services
  2. Isolation of failures - If Service A fails, it won't affect the resilience patterns protecting Service B
  3. Independent configuration - Different backends may require different circuit breaker thresholds, concurrency limits, rate limits, or retry policies

==== Instance-Aware vs. Non-Instance-Aware Patterns

Different resilience patterns have different requirements for instance separation:

===== Instance-Aware Patterns (MUST NOT Share)

These patterns maintain state that is specific to a particular service and MUST have separate instances:

  • CircuitBreaker - Tracks failure rates and state (OPEN/CLOSED/HALF_OPEN) per service

[source,java]

// CORRECT: Separate CircuitBreaker for each service CircuitBreaker paymentServiceCB = CircuitBreaker.ofDefaults("paymentService"); CircuitBreaker inventoryServiceCB = CircuitBreaker.ofDefaults("inventoryService"); CircuitBreaker notificationServiceCB = CircuitBreaker.ofDefaults("notificationService");

// WRONG: Sharing one CircuitBreaker across multiple services CircuitBreaker sharedCB = CircuitBreaker.ofDefaults("shared"); // DON'T DO THIS! // If one service fails, the circuit opens for ALL services!

  • Bulkhead (both SemaphoreBulkhead and ThreadPoolBulkhead) - Manages concurrent call limits per service

[source,java]

// CORRECT: Separate Bulkhead for each service Bulkhead paymentBulkhead = Bulkhead.ofDefaults("paymentService"); Bulkhead inventoryBulkhead = Bulkhead.ofDefaults("inventoryService");

// WRONG: Sharing limits resource isolation benefits Bulkhead sharedBulkhead = Bulkhead.ofDefaults("shared"); // DON'T DO THIS!

  • RateLimiter - Controls request rate per service

[source,java]

// CORRECT: Different rate limits for different services RateLimiter apiRateLimiter = RateLimiter.ofDefaults("externalAPI"); RateLimiter dbRateLimiter = RateLimiter.ofDefaults("database");

===== Non-Instance-Aware Patterns (CAN Share, But Better Not To)

These patterns create fresh context for each execution and don't maintain service-specific state:

  • Retry - Configuration can be shared, but unique instances are still recommended for proper metrics
  • TimeLimiter - Timeout settings can be shared if identical across services

[source,java]

// TECHNICALLY OK: Retry doesn't maintain state between calls Retry sharedRetry = Retry.ofDefaults("shared");

// BETTER: Unique instances provide better metrics and monitoring Retry paymentRetry = Retry.ofDefaults("paymentService"); Retry inventoryRetry = Retry.ofDefaults("inventoryService");

// Now you can track: // - How many retry attempts failed for paymentService specifically // - How many retry attempts failed for inventoryService specifically

==== Recommended Approach: Always Use Unique Instances

Even for patterns that can be shared, creating unique instances is the recommended approach because:

  • Better observability - Metrics are tagged by instance name, letting you see which backend is struggling
  • Easier troubleshooting - Clear separation makes debugging production issues simpler
  • Future flexibility - If you later need different configurations per service, instances are already separated

===== Complete Example: Multiple Services

[source,java]

// You have 3 backend services to protect public class ServiceOrchestrator {

// Payment Service protection
private final CircuitBreaker paymentCB = CircuitBreaker.ofDefaults("paym
View on GitHub
GitHub Stars10.6k
CategoryDesign
Updated51m ago
Forks1.4k

Languages

Java

Security Score

100/100

Audited on Mar 26, 2026

No findings