Start Learning
Javaneer
Back to stage
Module 7·Microservices & Spring Cloud

Resilience: Circuit Breakers

Stop one failing service from cascading: circuit breakers, retries, timeouts, and fallbacks with Resilience4j.

16 min readAdvanced
On this page

In a monolith, a slow method is a slow method. In a distributed system, a slow service is contagious: if lending calls catalog and catalog hangs, lending's threads pile up waiting, and soon lending falls over too - then whatever calls lending. One failure cascades into an outage. Resilience4j gives you the patterns to stop the spread.

The circuit breaker

The headline pattern is the circuit breaker, named after the electrical kind. It watches calls to a downstream service; when failures cross a threshold, it opens - and for a while, calls fail fast (with a fallback) instead of waiting on the broken service:

@CircuitBreaker(name = "catalog", fallbackMethod = "cachedBook")
public Book fetchBook(String isbn) {
    return catalogClient.getBook(isbn);      // may fail if catalog is down
}

private Book cachedBook(String isbn, Throwable cause) {
    return bookCache.get(isbn);              // graceful fallback
}

The breaker has three states: closed (calls flow normally), open (calls fail fast after too many failures), and half-open (it periodically lets a trial call through to see if the service has recovered, then closes if it has).

A circuit breaker in your house

When a wire shorts, the breaker in your fuse box trips and cuts power to that circuit - protecting the rest of the house from the fault and preventing a fire. It doesn't stay off forever; you reset it once the problem is fixed. A software circuit breaker does exactly this: it trips when a service keeps failing, protects the callers from piling up on it, and later tries again to see if it's healthy.

The rest of the toolkit

Resilience4j bundles complementary patterns:

  • Retry — try a failed call a few times (for transient blips), with backoff.
  • Timeout — never wait forever; bound how long a call may take.
  • Rate limiter & bulkhead — cap concurrency so one dependency can't consume all your threads.

Used together: a timeout stops one call hanging, a retry rides out a blip, and a circuit breaker gives up when the service is truly down - returning a fallback so the user still gets a degraded-but-working response.

Always have a fallback plan

Fail fast is only half of resilience; the other half is degrading gracefully. A fallback - a cached value, a default, a clear "temporarily unavailable" - keeps your service usable when a dependency is down, instead of failing the whole request.

Stop the cascade

Lending calls catalog on every request. Catalog goes down and starts timing out. Without any resilience, describe how this takes lending down too - then explain how a circuit breaker with a fallback keeps lending working (in a degraded way).

What does a circuit breaker do when a downstream service keeps failing?

Key takeaways

  • In distributed systems, a failing service cascades: callers block waiting on it and fall over too.
  • A circuit breaker (Resilience4j) opens when failures cross a threshold, failing fast with a fallback so calls don't pile up.
  • Its states are closed (normal), open (fail fast), and half-open (trial calls to test recovery).
  • Combine with retry (ride out blips), timeout (bound waiting), and bulkheads (cap concurrency).
  • Resilience means degrading gracefully with a fallback, not just failing - keep the service usable when a dependency is down.
Was this lesson helpful?
Edit this page on GitHub