The Request That Looked Like a Forward, But Wasn’t
Imagine this flow:
At first glance, it may look like Backend A is simply forwarding the request to Backend B.
But in Spring applications, the word forward has a very specific meaning. And when Backend A uses FeignClient to call Backend B, that is not technically a forward.
It is a new HTTP call.
What Is a Real HTTP Forward?
A real HTTP forward happens inside the same web application.
For example, in Spring MVC:
The flow is:
No new browser request is created. The same HttpServletRequest continues inside the server.
That means request attributes are preserved:
The /target endpoint can still read that attribute because it is the same request.
What Happens with FeignClient?
FeignClient works differently.
Example:
@FeignClient(name = "patient-service")
public interface PatientClient {
@GetMapping("/patients/{id}")
PatientDto getPatient(@PathVariable Long id);
}
When a controller uses this client:
@GetMapping("/patients/{id}")
public PatientDto getPatient(@PathVariable Long id) {
return patientClient.getPatient(id);
}
The flow is:
Browser -> Backend A
Backend A -> new HTTP request -> Backend B
Backend B -> response -> Backend A
Backend A -> response -> Browser
So Backend A is not forwarding the same request. It is receiving one request and creating another one.
The Main Difference
| Aspect | HTTP Forward | FeignClient |
|---|---|---|
| Request | Same request | New request |
| Target | Same app/server | Another API/service |
| Browser URL changes? | No | No |
| Request attributes preserved? | Yes | No |
| Headers propagated automatically? | Same request headers available | Must be copied manually |
| Network call? | No external call | Yes |
Why This Matters
With a real forward, everything stays inside one application.
With FeignClient, we enter service-to-service communication. That means we must think about:
- Timeouts
- Retries
- Authentication
- Header propagation
- Correlation IDs
- Logging
- Distributed tracing
- Downstream failures
For example, if the original request contains:
Backend B will not automatically receive those headers. We need to explicitly propagate them, usually with a Feign RequestInterceptor.
Better Wording
Instead of saying:
A more accurate sentence is:
Backend A acts as a proxy: it receives the client request and creates a new HTTP request to Backend B using FeignClient.
Happy coding! 💻