Why Is Spring Dropping Feign for @HttpExchange?
The article analyzes Spring Framework’s new native HTTP Interface (@HttpExchange), comparing it with OpenFeign in terms of architecture, dependency management, performance, and suitability for reactive programming, and provides migration guidance and practical code examples.
Introduction
Spring Framework 6 silently introduced a native declarative HTTP client called @HttpExchange , which is now deeply integrated into Spring Boot 4.x and recommended as a replacement for OpenFeign. This article dissects the differences, performance impact, and migration considerations.
1. Relationship Between Feign and @HttpExchange
Both are declarative HTTP clients, but their hierarchy differs.
Feign is a Netflix‑originated library that lives in the Spring Cloud ecosystem; using it requires the spring-cloud-starter-openfeign dependency and the @EnableFeignClients annotation.
@HttpExchange is a native feature of Spring Framework 6, part of the core framework, and does not depend on any Spring Cloud components.
Analogy: Feign is a “third‑party renovation crew” you have to hire separately, while @HttpExchange is the “developer‑provided finish” that comes with the house.
2. What Changed? – Code Comparison
2.1 Feign Definition
@FeignClient(name = "user-service", url = "${user.service.url}")
public interface UserClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
@PostMapping("/users")
User createUser(@RequestBody User user);
@GetMapping("/users")
List<User> getUsers(@RequestParam("page") int page, @RequestParam("size") int size);
}Dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>Enable in the main class:
@EnableFeignClients
@SpringBootApplication
public class Application { ... }2.2 @HttpExchange Definition
@HttpExchange("http://localhost:8080/api/v1")
public interface UserClient {
@GetExchange("/users/{id}")
User getUserById(@PathVariable Long id);
@PostExchange("/users")
User createUser(@RequestBody User user);
@GetExchange("/users")
List<User> getUsers(@RequestParam int page, @RequestParam int size);
}No extra dependency is required because Spring 6 already provides HTTP Interface support.
Configuration uses HttpServiceProxyFactory to create a dynamic proxy:
@Configuration
public class HttpClientConfig {
@Bean
public UserClient userClient(RestClient restClient) {
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
return factory.createClient(UserClient.class);
}
}The proxy can work with either RestClient (synchronous) or WebClient (reactive).
3. Fundamental Architectural Differences
3.1 Feign Proxy Mechanism
Feign uses JDK dynamic proxies. When a method is invoked, the proxy builds an HTTP request from the annotations and sends it via Apache HttpClient, OkHttp, or HttpURLConnection. In a Spring Cloud environment it also integrates LoadBalancerClient for service discovery and load balancing. Feign is inherently blocking; each request occupies a thread, leading to potential thread‑pool bottlenecks under high concurrency.
3.2 @HttpExchange Proxy Mechanism
@HttpExchange relies on HttpServiceProxyFactory. The interface only declares the contract; the actual execution is delegated to RestClient (blocking) or WebClient (reactive). The factory automatically selects the execution strategy based on the return type (e.g., CompletableFuture, Mono, Flux → WebClient; ordinary types → RestClient). This design natively supports reactive programming and integrates seamlessly with Spring WebFlux.
Benchmark: under 1,000 concurrent requests, @HttpExchange achieves ~40% higher throughput and 35% lower memory consumption compared with OpenFeign.
4. Why Spring Is Moving Away From Feign
Feign is heavyweight: it requires the Spring Cloud starter and is tied to the Spring Cloud version.
Feign’s blocking design makes integration with reactive stacks cumbersome.
Spring wants a fully native solution that does not depend on third‑party components.
Version alignment and maintenance cost are lower for a core framework feature.
Configuration overhead for many interfaces can become repetitive; Spring 7 introduces an HTTP Service Registry and @ImportHttpServices to simplify this.
5. Pros and Cons
Feign Advantages
Mature ecosystem with built‑in service discovery, load balancing, and circuit breaking.
High developer familiarity after a decade of usage.
Simple configuration – just declare the interface.
Rich third‑party extensions (encoders, decoders, logging, retries).
Feign Disadvantages
Requires Spring Cloud dependency, making it heavy for non‑microservice projects.
Blocking I/O limits scalability.
Not compatible with reactive programming out of the box.
Version must stay in sync with Spring Cloud releases.
@HttpExchange Advantages
Part of Spring Framework core – no extra dependencies.
Supports both blocking and reactive models automatically.
Benchmark shows ~40% higher throughput and 35% lower memory usage under load.
Seamless integration with WebFlux and back‑pressure support.
Long‑term maintenance by the Spring Framework team.
@HttpExchange Disadvantages
Community and ecosystem are less mature than Feign’s.
Configuration can be verbose (manual HttpServiceProxyFactory), though Spring 7’s @ImportHttpServices mitigates this.
Team familiarity may be lower; migration incurs learning cost.
Load balancing must be added manually (supported starting Spring Cloud 2026.0).
6. When to Use Which
Stick with Feign
Existing legacy projects with many Feign interfaces where migration cost is high.
Deep reliance on Spring Cloud features such as service discovery, load balancing, and circuit breaking.
Team is highly experienced with Feign and prefers the familiar API.
Application does not need reactive programming.
Adopt @HttpExchange
New projects with no historical baggage.
Need for reactive programming (WebFlux) or high‑concurrency scenarios.
Desire for lighter dependencies and better performance.
Goal to keep the technology stack minimal and fully native to Spring Framework.
7. Migration Steps
Introduce @HttpExchange on all newly created interfaces; leave existing Feign code untouched.
Gradually refactor low‑traffic, simple Feign interfaces to @HttpExchange.
After the team is comfortable, migrate high‑traffic core interfaces.
Leverage Spring 7’s @ImportHttpServices to simplify configuration.
8. Final Thoughts
Spring is not “killing” Feign; it is offering a lighter, more flexible native alternative. If your project is tightly coupled with Spring Cloud, Feign remains a solid choice. However, for new services, performance‑critical workloads, or reactive stacks, @HttpExchange is worth serious evaluation.
Official resources:
Spring Framework HTTP Interface documentation: https://docs.spring.io/spring-framework/reference/web/webflux-http-interface-client.html
HTTP Service Client Enhancements blog post: https://spring.io/blog/2025/09/23/http-service-client-enhancements
Architecture Diagrams
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
