1. Failure Handling
  2. Policy Composition
    1. Typical Composition
  3. Supported Policies

Failure Handling

Failsafe policies determine which execution results or failures to handle and how to handle them. By default, policies handle any Exception that is thrown. But policies can also be configured to handle more specific failures or conditions:

  .handle(ConnectException.class, SocketException.class)
  .handleIf(failure -> failure instanceof ConnectException);

They can also be configured to handle specific results or result conditions:

  .handleResultIf(result -> result == null);  

When multiple handle methods are configured, they are logically OR’ed.

Policy Composition

Policies can be composed in any way desired, including multiple policies of the same type. Policies handle execution results in reverse order, similar to the way that function composition works. For example, consider:

Failsafe.with(fallback, retryPolicy, circuitBreaker, timeout).get(supplier);

This results in the following internal composition when executing the supplier and handling its result:


This means the Supplier is evaluated first, then it’s result is handled by the Timeout, then the CircuitBreaker, the RetryPolicy, and the Fallback. Each policy makes its own determination as to whether the result represents a failure. This allows different policies to be used for handling different types of failures.

Typical Composition

A typical Failsafe configuration that uses multiple policies might place a Fallback as the outer-most policy, followed by a RetryPolicy, CircuitBreaker, and a Timeout as the inner-most policy:

Failsafe.with(fallback, retryPolicy, circuitBreaker, timeout)

That said, it really depends on how the policies are being used, and different compositions make sense for different use cases.

Supported Policies

Read about the built-in policies that Failsafe supports: