RestTemplate vs WebClient vs Feign vs HTTP Interface
Fast recall
Quick revision
Core answer
@HttpExchange) is the modern default — declarative, works with RestClient (sync) or WebClient (reactive), minimal boilerplate, built-in. WebClient is the reactive/non-blocking client — use for high-concurrency or WebFlux apps. `RestClient` (Spring 6.1+) is the modern synchronous replacement for RestTemplate — fluent, built on top of same HTTP infra. RestTemplate is in maintenance mode — still supported, no new features, migrate away for new code. OpenFeign is still popular via Spring Cloud OpenFeign — declarative like HTTP Interface but external dep; use if you're already on Spring Cloud. Default pick for new Spring 6+ code: `@HttpExchange` backed by `RestClient` for sync or `WebClient` for reactive. Wrap with Resilience4j for circuit breaking, timeouts, retries; tune connection pool; propagate trace headers.Modern Spring HTTP client choice; resilience and observability
Using RestTemplate for new code; no timeouts; no connection pool tuning; no circuit breaker; blocking in WebFlux
Discuss @HttpExchange, Spring 6 RestClient, Project Loom virtual threads, Resilience4j integration, distributed tracing propagation
Interview-ready guide
Interview answer
In 2026, pick by model and async needs.
Spring 6 HTTP Interface (@HttpExchange) is the modern default
- Declarative interface-based
- Works with RestClient (sync) or WebClient (reactive)
- Minimal boilerplate; built-in to Spring 6+
- Reduces need for Feign in Spring-native apps
RestClient (Spring 6.1+)
- Modern synchronous replacement for RestTemplate
- Fluent API
- Built on same HTTP infra
- Recommended synchronous choice for new code
WebClient
- Reactive, non-blocking
- Used in WebFlux apps; whenever non-blocking I/O needed in Spring MVC
- Streaming, SSE, async responses
- With Project Loom virtual threads, the pure concurrency advantage softens; still right for streaming or fully reactive pipelines
RestTemplate
- Legacy synchronous; in maintenance mode
- No new features since Spring 5
- For new code, use RestClient or @HttpExchange
OpenFeign (Spring Cloud OpenFeign)
- Declarative HTTP client from Netflix OSS
- Similar to @HttpExchange conceptually but richer ecosystem (Resilience4j integration, logging, custom encoders)
- Still widely used in Spring Cloud stacks
- Case weakens in Spring 6+ with native @HttpExchange
JDK HttpClient, Apache HttpClient 5, OkHttp
- Low-level libraries Spring can sit on top of
- Use for specific features (HTTP/2 tuning, HTTP/3, connection pooling)
Default pick for Spring 6+ new code
- @HttpExchange backed by RestClient for sync
- Or WebClient for reactive
- Wrap with Resilience4j for circuit breaking, timeouts, retries
- Tune connection pool
- Propagate trace headers
Usage examples
@HttpExchange
- Define interface with @GetExchange, @PostExchange annotations
- Configure with RestClient builder
- Build via HttpServiceProxyFactory + RestClientAdapter
- Cleaner than Feign for simple cases; no external dep
RestClient
- Fluent: builder.baseUrl().defaultHeader()
- client.post().uri().body().retrieve().onStatus().body()
- Imperative modern sync
WebClient
- Reactive; Mono/Flux
- client.get().uri().retrieve().onStatus().bodyToMono().timeout()
- Use in WebFlux; can .block() in MVC (but if everywhere blocking, don't need WebClient)
OpenFeign
- @FeignClient(name, url); Spring Cloud discovers via Eureka/Consul
- Integrates with LoadBalancer, Resilience4j, Sleuth
Production concerns
Timeouts non-negotiable
- Connect timeout: 1 to 2s internal, 5s external
- Read timeout: 2 to 10s internal, 10 to 30s external
- Total/request timeout: overall ceiling
- Default clients often have huge or no timeouts; requests hang forever
Connection pool tuning
- Default pool sizes rarely fit production
- Tune: max connections per route, total max, idle timeout, evict policy
- Monitor pool saturation
- Example: Apache HttpClient 5 with PoolingHttpClientConnectionManager
Resilience4j for circuit breaker, retry, bulkhead, timeout
- @CircuitBreaker, @Retry, @Bulkhead, @TimeLimiter annotations
- Config in application.yml: slidingWindowSize, failureRateThreshold, waitDurationInOpenState, maxAttempts, timeoutDuration
- Fallback method for graceful degradation
Observability
- Metrics: Micrometer auto-instruments; http.client.requests with URI, method, status, outcome
- Tracing: Spring + OpenTelemetry / Micrometer Tracing auto-propagates traceparent
- Logging: careful not to log bodies (PII/secrets); log correlation id, URL, status, duration
Auth propagation
- Propagate JWT / auth context for on-behalf-of-user
- Service-to-service: OAuth2 client credentials or mTLS
- ExchangeFilterFunction (WebClient), RestClient interceptors, or RequestInterceptor (Feign) to inject tokens
MDC / tracing headers propagation
- When switching threads, MDC can be lost
- Spring Cloud Sleuth / Micrometer Tracing handle propagation
- Verify trace IDs appear in downstream logs
Error handling patterns
- Don't let RestClientException bubble unfiltered; map to domain exceptions
- 4xx client error: don't retry
- 5xx server error: retry idempotent
- 429 rate limited: back off
- 503 unavailable: retry
- Idempotency keys on non-idempotent POSTs when retrying
Trade-offs
RestClient vs WebClient
- Sync RestClient: simpler debugging, stack traces, Transactional boundaries
- Reactive WebClient: non-blocking, streaming, high concurrency, backpressure
- With Project Loom, sync Tomcat + RestClient handles high concurrency efficiently
- Still pick WebClient for streaming, fully reactive pipelines, or WebFlux apps
@HttpExchange vs Feign
- @HttpExchange native to Spring 6; no extra dep
- Feign has deeper ecosystem (Spring Cloud LoadBalancer, decoders)
- New code on Spring 6+: @HttpExchange usually wins
- Existing Spring Cloud projects: Feign entrenched
When NOT to use declarative
- Complex dynamic URL; computed headers per request
- Per-call ExchangeFilterFunction or interceptor
- Streaming with per-chunk logic
- Use imperative RestClient or WebClient directly
HTTP/2 adoption
- WebClient (Reactor Netty), RestClient (JDK HttpClient), Apache HttpClient 5 all support
- Multiplexing reduces connection overhead
HTTP/3 (QUIC) emerging
- Experimental; production niche
gRPC as alternative
- Internal microservice calls often better in gRPC: HTTP/2, Protobuf, strong types
- REST still default for public APIs
Circuit breaker antipattern
- Fallback that masks errors silently
- Fallback should return cached/default, queue for later, or clearly indicate failure
- Don't paper over bad dependencies; fix them
Retry antipattern
- Retrying non-idempotent POSTs without idempotency keys
- Retrying on client errors
- Exponential backoff + jitter; cap attempts (3 typical)
Timeout antipattern
- 30s default; thread pool exhaustion
- Aggressive internal timeouts
- Timeout budget accounts for retries
Testing
- MockWebServer (okhttp): full HTTP mock
- WireMock: classic Java HTTP mock
- MockRestServiceServer (Spring): mock client side
- Prefer real HTTP mocks over mocking RestTemplate
Security
- TLS for all external; validate certificates
- mTLS for service-to-service (Istio or manual)
- Secrets in Vault/Secrets Manager
- Never log tokens
The strategic answer
- Spring 6+ new code: @HttpExchange + RestClient (or WebClient) default
- RestTemplate only for legacy maintenance
- OpenFeign where Spring Cloud stack entrenched
- Timeouts, connection pool, Resilience4j are essential
- Observability with Micrometer and distributed tracing
- Test with MockWebServer/WireMock; not by mocking client directly
- Consider gRPC for internal service-to-service calls
RestTemplate vs WebClient vs Feign vs HTTP Interface
Direct Answer
In 2026, pick by model and async needs: Spring 6 HTTP Interface (@HttpExchange) is the modern default — declarative, works with RestClient (sync) or WebClient (reactive), minimal boilerplate, built-in. WebClient is the reactive/non-blocking client — use for high-concurrency or WebFlux apps. RestClient (Spring 6.1+) is the modern synchronous replacement for RestTemplate — fluent, built on top of same HTTP infra. RestTemplate is in maintenance mode — still supported, no new features, migrate away for new code. OpenFeign is still popular via Spring Cloud OpenFeign — declarative like HTTP Interface but external dep; use if you're already on Spring Cloud. Default pick for new Spring 6+ code: @HttpExchange backed by RestClient for sync or WebClient for reactive. Wrap with Resilience4j for circuit breaking, timeouts, retries; tune connection pool; propagate trace headers.
Common Mistakes & Pitfalls
Using RestTemplate for new code; no timeouts; no connection pool tuning; no circuit breaker; blocking in WebFlux
Check your understanding
Answer these without looking back at the article.
- How does @HttpExchange work under the hood vs Feign?
- When does Project Loom change the RestClient vs WebClient decision?
- How do you propagate distributed tracing headers through WebClient chained calls?
- What are the Resilience4j configurations you'd set for an external payment API?
Related interview prep categories
1Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.