For Golang projects, Failsafe-go has been released! See the project website for more info.

Overview

Failsafe is a lightweight, zero-dependency library for handling failures in Java 8+. It has a concise API for handling everyday use cases and the flexibility to handle everything else. Failsafe works by wrapping executable logic with one or more resilience policies, which can be combined and composed as needed.

Setup

Add the latest Failsafe dependency to your project.

Getting Started

To see how Failsafe works, we’ll create a retry policy that defines which failures to handle and when retries should be performed:

RetryPolicy<Object> retryPolicy = RetryPolicy.builder()
  .handle(ConnectException.class)
  .withDelay(Duration.ofSeconds(1))
  .withMaxRetries(3)
  .build();

We can then execute a Runnable or Supplier with retries:

// Run with retries
Failsafe.with(retryPolicy).run(() -> connect());

// Get with retries
Connection connection = Failsafe.with(retryPolicy).get(() -> connect());

Asynchronous Execution

Executing a Runnable or Supplier asynchronously with a policy is simple:

// Run with retries asynchronously
CompletableFuture<Void> future = Failsafe.with(retryPolicy).runAsync(() -> connect());

// Get with retries asynchronously
CompletableFuture<Connection> future = Failsafe.with(retryPolicy).getAsync(() -> connect());

Composing Policies

Multiple policies can be arbitrarily composed to add additional layers of resilience or to handle different failures in different ways:

var fallback = Fallback.of(this::connectToBackup);
var circuitBreaker = CircuitBreaker.ofDefaults();
var timeout = Timeout.of(Duration.ofSeconds(10));

// Get with fallback, retries, circuit breaker, and timeout
Failsafe.with(fallback, retryPolicy, circuitBreaker, timeout).get(this::connect);

Order does matter when composing policies. See the policy composition overview for more details.

Failsafe Executor

Policy compositions can also be saved for later use via a FailsafeExecutor:

FailsafeExecutor<Object> executor = Failsafe.with(retryPolicy).compose(circuitBreaker);
executor.run(this::connect);

Further Reading

Read more about policies and how they’re used, then explore some of Failsafe’s other features in the site menu.