Skip to content

Instantly share code, notes, and snippets.

@mike-seger
Last active March 17, 2025 17:57
Show Gist options
  • Save mike-seger/56843710e7c4bb5944bbc2206c776b59 to your computer and use it in GitHub Desktop.
Save mike-seger/56843710e7c4bb5944bbc2206c776b59 to your computer and use it in GitHub Desktop.
What are the key differences between Resilience4j and dev.failsafe?

Resilience4j and dev.failsafe (Failsafe) are both fault-tolerance libraries for Java, but they have key differences in their architecture, feature set, and intended use cases. 1. Design and Philosophy

  • Resilience4j : Built specifically for resilience in microservices, inspired by Netflix Hystrix. It provides various fault-tolerance mechanisms as independent modules.

  • Failsafe : A more lightweight and flexible general-purpose retry/fault-tolerance library with a functional and fluent API.

2. Features Comparison

Feature Resilience4j Failsafe
Retry ✅ Yes (configurable backoff strategies) ✅ Yes (exponential, jitter, etc.)
Circuit Breaker ✅ Yes (with half-open state) ✅ Yes (adaptive circuit breaker)
Rate Limiting ✅ Yes (token-bucket based) ❌ No
Bulkhead (Concurrency Limits) ✅ Yes (thread-based & semaphore-based) ❌ No
Time Limiting ✅ Yes (Timeout feature) ✅ Yes (execution timeouts)
Fallback Handling ✅ Yes ✅ Yes
Event Listeners / Metrics ✅ Yes (with Micrometer integration) ✅ Yes (custom event listeners)
Integration with Spring Boot ✅ Yes (Spring Boot starters available) ❌ No native support, manual integration needed

3. API Design

  • Resilience4j : Uses a decorator pattern where each fault-tolerance feature is an independent module (e.g., Retry, CircuitBreaker, etc.). You explicitly decorate function calls.
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("myCircuitBreaker");
Supplier<String> decoratedSupplier = CircuitBreaker.decorateSupplier(circuitBreaker, () -> "Hello");
String result = Try.ofSupplier(decoratedSupplier).recover(throwable -> "Fallback").get();
  • Failsafe : Provides a fluent API that chains policies together in a single execution block.
RetryPolicy<Object> retryPolicy = RetryPolicy.builder()
    .handle(IOException.class)
    .withBackoff(1, 10, ChronoUnit.SECONDS)
    .build();

CircuitBreaker<Object> circuitBreaker = CircuitBreaker.builder()
    .withFailureThreshold(3, 10)
    .build();

Failsafe.with(circuitBreaker, retryPolicy)
    .onSuccess(e -> System.out.println("Success!"))
    .onFailure(e -> System.out.println("Failure!"))
    .run(() -> doSomething());

4. Performance & Overhead

  • Resilience4j : Slightly more overhead because it provides additional features like rate limiting, bulkhead, and detailed metrics.

  • Failsafe : More lightweight and efficient for simple retry + circuit breaker needs.

5. Use Cases

  • Use Resilience4j when:

    • You need fine-grained control over resilience mechanisms.

    • You are working with a Spring Boot microservice.

    • You require built-in monitoring (Micrometer, Prometheus).

    • You need bulkhead or rate limiting.

  • Use Failsafe when:

    • You need a simple, lightweight fault-tolerance solution.

    • You want an easy-to-use API without external dependencies.

    • You prefer chaining multiple policies fluently.

    • You are building a non-Spring application or need a library-agnostic solution.

6. Integration & Ecosystem

  • Resilience4j : Well-integrated with Spring Boot (Spring Cloud Circuit Breaker, Micrometer, Actuator).

  • Failsafe : More suited for standalone Java applications or frameworks that do not rely on Spring.

Conclusion If you're working on a Spring Boot microservice , Resilience4j is the better choice due to its rich feature set and built-in integration. However, if you want lightweight, simple, and flexible fault tolerance , especially outside of Spring Boot, dev.failsafe is a great alternative.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment