Failsafe, a lightweight fault tolerance library for Java 8+, launched the major 3.0 release in November 2021. This release introduced some breaking changes to the API, a new dev.failsafe
package and new Maven groupId
, a builder API for all the policies, plus some redesigned methods for Circuit Breaker, Retry Policy, Standalone Execution and Async Execution.
More recently, Failsafe announced the availability of version 3.2 which introduced new Rate Limiter and Bulkhead policies.
Failsafe policies determine how to handle an eventual failure. By default, they handle every exception thrown, but that may be customized to more specific failures.
The different resilience policies that Failsafe now supports are: Retry Policy that defines when retries should be performed; Circuit Breaker that temporarily disables executions in order to prevent system overload; Rate Limiter that defines the rate of allowed executions; Timeout that cancels an execution if it takes too long to respond; Bulkhead that limits the number of concurrent executions; and Fallback that provides an alternative result for a failed execution.
Circuit Breaker supports both count-based and time-based patterns. The former counts the number of failures up to a limit while the latter counts the number of failures in a given period of time.
These policies can also be composed together to define complex custom behaviors.
In the code snippet shown below, an example of composition of multiple policies:
Fallback<Object> fallback = Fallback.of(this::connectToBackup);
CircuitBreaker<Object> circuitBreaker = CircuitBreaker.ofDefaults();
Timeout<Object> timeout = Timeout.of(Duration.ofSeconds(10));
// Get with fallback, retries, circuit breaker, and timeout
Failsafe.with(fallback)
.compose(retryPolicy)
.compose(circuitBreaker)
.compose(timeout)
.get(this::connect);
In accordance with function composition, the policies are applied in reverse order. Therefore, in the example above, the first is timeout
, then circuitBreaker
and finally retryPolicy
.
As well as synchronous execution, Failsafe integrates also with asynchronous code like Java’s CompletableFuture
. In the example shown below, a retry policy is applied to every stage of the Async operation.
CompletableFuture.supplyAsync(() -> Failsafe.with(retryPolicy).get(() -> "foo"))
.thenApplyAsync(value -> Failsafe.with(retryPolicy).get(() -> value + "bar"))
.thenAccept(System.out::println);
The concepts behind Failsafe are similar to other tools like Netflix Hystrix and Resilience4J. However, contrary to these tools, Failsafe has no dependencies from external libraries.
Failsafe is used, among the others, by important players in the open-source landscape such as Eclipse MicroProfile, Apache Samza, Apache Pulsar and Presto.