Overview
Three HTTP clients ship with Spring. RestTemplate is in maintenance mode. RestClient (Spring 6.1+) replaces it for blocking code. WebClient is the reactive option.
Official: RestClient, WebClient.
Table of contents
- Which client to pick
RestClient(blocking)WebClient(reactive)RestTemplate(legacy)- Timeouts and pooling
- Retries & circuit breakers
- Interview questions
- Summary
1. Which client to pick
| Client | Style | Use when |
|---|---|---|
RestClient |
Blocking, fluent | New blocking code in Spring MVC |
WebClient |
Reactive | WebFlux stack or you need non-blocking I/O |
RestTemplate |
Blocking, legacy | Existing code only — don’t pick for new work |
2. RestClient (blocking)
@Bean
RestClient ordersClient(RestClient.Builder builder) {
return builder
.baseUrl("https://api.example.com")
.defaultHeader("Authorization", "Bearer " + token)
.build();
}
Order order = restClient.get()
.uri("/orders/{id}", 42)
.retrieve()
.body(Order.class);
Fluent and synchronous. Backed by Java’s HttpClient or Apache HttpComponents.
3. WebClient (reactive)
Mono<Order> order = webClient.get()
.uri("/orders/{id}", 42)
.retrieve()
.bodyToMono(Order.class);
Non-blocking. Needs Reactor on the classpath. Fits the WebFlux stack but can be used from Spring MVC too — just don’t .block() casually.
4. RestTemplate (legacy)
Still in the codebase everywhere. No active development — migrate to RestClient for new blocking code.
5. Timeouts and pooling
The single most common production bug: no read timeout → one slow upstream hangs your threads forever.
Always set:
- Connect timeout — how long to wait for the TCP/TLS handshake.
- Read/response timeout — how long to wait for the response.
- Connection pool size — match expected concurrency.
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(2))
.build();
RestClient client = RestClient.builder()
.requestFactory(new JdkClientHttpRequestFactory(httpClient))
.build();
6. Retries & circuit breakers
Use Resilience4j (or Spring Cloud Circuit Breaker) for:
- Retry with exponential backoff + jitter — only on idempotent operations (GET, PUT). Retrying a POST without idempotency keys can charge a card twice.
- Circuit breaker — stop calling a failing dependency to give it time to recover.
7. Interview questions
Q: RestClient vs WebClient?
A: RestClient is blocking and synchronous. WebClient is reactive and non-blocking. Pick based on your stack and concurrency model.
Q: Why avoid RestTemplate in new code?
A: It’s in maintenance mode — no new features. Use RestClient for blocking work.
Q: What timeouts must you set on outbound HTTP? A: Connect, read/response, and pool max. Default infinite read timeout is the most common production landmine.
Q: When is retrying safe? A: When the operation is idempotent. Use idempotency keys for unsafe verbs like POST.
8. Summary
| Client | Model |
|---|---|
| RestClient | Blocking, modern |
| WebClient | Reactive |
| RestTemplate | Legacy |
| Always set | Connect + read timeouts |
Next steps
Happy Learning