Feign Client Declarative HTTP & Resilience4j Circuit Breakers
- Last updated
- Prerequisites:
- Spring Boot REST basics
- Understanding of microservice communication and failure handling
- spring
- feign
- resilience4j
- circuit-breaker
- microservices
- http-client
Read at your depth
The practical view
OpenFeign makes HTTP clients declarative: @FeignClient(name = "users", url = "${users.url}") interface UserClient { @GetMapping("/users/{id}") User get(@PathVariable Long id); }. Spring creates a proxy implementing the interface that makes the HTTP calls. Resilience4j adds resilience patterns: CircuitBreaker, RateLimiter, Retry, TimeLimiter, Bulkhead. Wire them with annotations or a Registry: @CircuitBreaker(name = "users", fallbackMethod = "getFallback"). A circuit breaker trips after N failures, opens for a wait duration, then half-opens to test recovery.
The same idea in other frameworks
N/A — server-side Spring/Feign concern.N/A — Spring concern.N/A — Spring concern.N/A — Spring concern.Legacy vs modern
Raw RestTemplate calls vs Feign + circuit breaker
Hand-rolled HTTP calls with manual error handling are verbose and have no failure isolation; Feign + Resilience4j makes the client declarative and resilient.
ResponseEntity<User> r = restTemplate.getForEntity(
"http://users/users/" + id, User.class); // ❌ OLD: manual, no resilience@FeignClient(name = "users")
public interface UserClient { // ✅ NEW: declarative
@GetMapping("/users/{id}") User get(@PathVariable Long id);
}Interview gotchas
Context
This tests the fault-tolerance mechanics — interviewers want the CLOSED → OPEN → HALF_OPEN transitions and the sliding-window failure measurement that drives them.
The mechanical answer
The circuit breaker is a state machine. CLOSED (normal): calls pass through and outcomes are recorded in a sliding window (e.g. the last 10 calls or 10 seconds); when the failure rate exceeds the threshold (e.g. 50%), it transitions to OPEN. OPEN: calls fail fast (CallNotPermittedException) without hitting the downstream service — protecting it and freeing the caller's resources; this lasts waitDurationInOpenState (e.g. 5s). HALF_OPEN: after the wait, the breaker lets a small number of trial calls through to test whether the downstream has recovered; if they succeed (below the threshold), it returns to CLOSED; if they fail, it reopens. This prevents a broken service from being hammered while still allowing automatic recovery. The fallback method is invoked for the failing calls so the caller gets a graceful response instead of an exception.
Trap
The naive answer is 'a circuit breaker retries failed calls'. It blocks calls when open (fail-fast), it doesn't retry — retry is a separate Resilience4j pattern. Another trap: setting the window too small (e.g. 1 call) makes the breaker trip on a single blip, and too large delays detection. Candidates who describe the three states and the window math show real understanding.
Context
This probes the client-selection trade-off — interviewers want to know the declarative-proxy model's pros/cons vs the more manual RestTemplate and the reactive WebClient.
The mechanical answer
Feign is a declarative, interface-based HTTP client: you define the contract as a Java interface with Spring MVC annotations, and Spring generates a proxy that implements the HTTP calls. It shines for typed, synchronous service-to-service calls in microservices (especially with Spring Cloud: load balancing, circuit breakers, request interceptors). RestTemplate is imperative and manual (build URLs, map responses) — more verbose but more explicit; still fine for simple clients. WebClient is the reactive client (Mono/Flux), non-blocking, for WebFlux or when you need streaming/async; it can also be used in MVC. Choose Feign for declarative typed contracts with Spring Cloud integration; WebClient for reactive/streaming; RestTemplate for legacy/simple blocking needs. Feign's proxy adds abstraction that can obscure the actual HTTP call, so debugging may require enabling Feign logging.
Trap
The naive answer is 'Feign is just a wrapper around RestTemplate'. It's a distinct code-generated proxy model. Another trap: assuming Feign is asynchronous — by default it's synchronous blocking; async requires a CompletableFuture return type or reactive support. Candidates who compare the three clients on the blocking/reactive and declarative axes show real depth.