Forward Proxy, Reverse Proxy, and the Problem of Point of View
I do not like the term “reverse proxy.”
It is not that the concept is bad. The concept is extremely useful. It is one of the most common patterns in web infrastructure. If you deploy applications, route traffic, terminate TLS, sit services behind a public hostname, put a CDN in front of an app, or send requests through an internal gateway, you are going to run into proxy-like things constantly.
The problem is the name.
“Reverse proxy” is one of those tech terms that makes sense only after you already know the thing it is being contrasted against. It does not describe the component by what it does. It describes the component by saying it is the reverse of another component.
That is a weird way to name something.
Most of the time, when I am deploying an application, I am not thinking:
I need the reverse version of a proxy.
I am thinking:
Traffic comes in here. Something receives it. Something terminates TLS. Something looks at the hostname or path. Something forwards the request to the correct backend process or service.
That sounds like a gateway, router, service front door, edge router, traffic router, or controlled middle layer.
It does not naturally sound like a “reverse proxy.”
The deeper problem is that once you start thinking about real systems, the forward proxy versus reverse proxy distinction starts to feel more like a matter of point of view than a clean universal category.
The Usual Explanation
The usual explanation goes something like this:
A forward proxy sits in front of the client.
A reverse proxy sits in front of the server.
That explanation is not wrong, but it is incomplete.
A forward proxy is usually controlled by the client side, or by the client’s organization or network. The client sends requests through the proxy to reach external services.
In plain text:
Client → forward proxy → outside service
A reverse proxy is usually controlled by the service side. External clients send requests to the service’s public entrypoint, and that entrypoint forwards requests to one or more internal services.
In plain text:
Many clients → reverse proxy → internal service
So the clean distinction is:
Forward proxy:
chosen by the requester side to reach outside services
Reverse proxy:
chosen by the service side to receive outside clients
That is the standard mental model.
And for simple diagrams, it works fine.
Both of Them Forward Requests
The immediate problem with the name “reverse proxy” is that a reverse proxy still forwards requests.
It may forward them to a process on the same machine.
It may forward them to another instance.
It may forward them to a container.
It may forward them to a service running on another host.
It may distribute them across a pool of backends and act as a load balancer.
It may terminate TLS, route by hostname, route by path, apply middleware, perform authentication, rewrite headers, add logging, enforce rate limits, or send the request somewhere else.
But the basic shape is still:
request comes in → middle layer receives it → request goes somewhere else
That is forwarding.
So the “reverse” is not about the direction of forwarding.
Both forward.
The “reverse” is about the administrative orientation of the proxy. A forward proxy is on the requester’s side of the relationship. A reverse proxy is on the service owner’s side of the relationship.
That distinction is real, but it is also more abstract than the name suggests.
The packets are not moving in reverse.
The request is not moving backward.
The component is not doing the opposite of forwarding.
It is still forwarding.
Everything Is in the Middle
The real world makes the terminology even more annoying because the world is full of middleboxes.
There are routers, NAT devices, load balancers, API gateways, CDNs, service mesh sidecars, SSH tunnels, bastion hosts, application gateways, ingress controllers, message brokers, event buses, and random internal services that call other internal services.
At some point, almost everything starts to look like:
Thing A → middle thing → Thing B
That is why “forward proxy” and “reverse proxy” can become confusing. The name depends on which relationship you are talking about and which system boundary you choose.
From one point of view, a box may be “in front of” the client.
From another point of view, it may be “in front of” the service.
From one point of view, it is forwarding traffic.
From another point of view, it is just an application calling a dependency.
From one point of view, it is a proxy.
From another point of view, it is a gateway, router, tunnel, load balancer, CDN edge, NAT device, or ordinary application server.
The physical shape alone does not answer the question.
You need to know the role the component is playing.
The NAS Question
Suppose I have a laptop, a NAS, and an external service.
If I send a request to my NAS, and then the NAS sends a request to an outside server, is the NAS a proxy?
Maybe.
But not necessarily.
If I am asking the NAS to perform some operation, and the NAS calls an external service as part of its own application logic, then calling it a proxy may be misleading.
That is more like this:
client → application → dependency
I asked the NAS to do something. The NAS, as an application, needed another service to complete the work.
That does not automatically make the NAS a proxy.
But if I am trying to reach the external service through the NAS, and the NAS exists specifically to receive my request and forward it on my behalf, then it starts to look proxy-like.
That is closer to:
client → proxy → destination
The difference is subtle but important.
The question is not merely:
Did one machine call another machine?
The better question is:
Was the middle component acting as a representative or intermediary for one side of the communication?
An application calling a dependency is not automatically a proxy.
A component receiving traffic on behalf of one side and forwarding it toward the intended destination is proxy-like.
The SSH Box Question
Now suppose I have a box that I SSH into, and from there I reach another machine.
Is the SSH box a proxy?
Again, maybe.
If I SSH into the box and manually run commands, the box is probably better described as a jump box or bastion host.
Laptop → SSH box
SSH box → internal target
The SSH box is a middle machine, but it is not necessarily acting as a transparent request-forwarding proxy. I am logging into it and then operating from that environment.
But if I create an SSH tunnel, the classification changes.
localhost:8080 → SSH tunnel → internal-service:80
Now local traffic is being forwarded through the SSH connection to another destination. That is much more proxy-like or gateway-like.
The same physical machine can participate in different patterns depending on how it is used.
That is the point.
The topology alone does not fully define the term. Usage matters. Abstraction matters. Intent matters.
The Backend Calls Another API Question
Now consider a normal web application.
A user sends a request to an application.
The application then calls another company’s API.
Is the application now a forward proxy?
Usually, no.
Most of the time, the application is not forwarding the user’s original request as a network intermediary. The application is receiving the user’s request, executing business logic, and making its own request to a dependency.
That is usually:
client → application → dependency
not:
client → proxy → destination
This distinction matters because otherwise almost every service-to-service call becomes a proxy relationship, and the term loses usefulness.
If LinkedIn receives a request from a user and then LinkedIn’s backend calls some other company’s API as part of its own business logic, I would not automatically call LinkedIn a forward proxy.
It is an application using a dependency.
But if LinkedIn exposed an endpoint whose purpose was specifically to forward a user’s request to another API, then that endpoint could become proxy-like.
Again, the question is not simply:
Did one server call another server?
The better question is:
Is this component acting as a middle layer for a communication the original caller is trying to have with another destination?
If yes, proxy-like.
If no, probably just an application dependency.
The Phone Hotspot Question
Now suppose my laptop is using my phone as a hotspot.
Is the phone a proxy?
Usually, not in the HTTP/application sense.
The phone is absolutely a middlebox. It forwards traffic. It may perform routing, NAT, address translation, and connectivity management.
But it is not necessarily an HTTP proxy.
My browser is not saying:
Please send this HTTP request to the phone so the phone can make the HTTP request on my behalf.
The phone is providing a network path.
So calling it a proxy may obscure more than it clarifies.
This is where the terminology gets irritating:
Not every middlebox is a proxy.
Not every forwarding thing is a proxy.
Not every proxy is called a proxy.
That is the real world.
A More Useful Proxy Test
Instead of starting with “forward” and “reverse,” I think it is more useful to first ask whether the component is proxy-like at all.
A component is proxy-like when:
1. One side is trying to reach some other side.
2. A middle component receives the communication instead.
3. The middle component forwards, transforms, filters, routes, or mediates that communication.
4. The middle component is part of the communication abstraction,
not merely an application making its own independent dependency call.
Then, only after that, ask whether it is more like a forward proxy or a reverse proxy.
If the proxy is chosen by the requester side,
people tend to call it a forward proxy.
If the proxy is chosen by the service side,
people tend to call it a reverse proxy.
Even then, the answer can depend on the boundary you choose.
“Chosen by the requester side” might mean configured by the user, configured by the user’s company, forced by a corporate network, inserted by an ISP, or wrapped in a VPN product.
“Chosen by the service side” might mean DNS points to it, a CDN sits in front of it, an ingress controller routes to it, a load balancer distributes across it, or a platform inserted it on behalf of the service owner.
The labels are useful, but they are not metaphysical truths.
They are contextual names for roles in a particular communication relationship.
Routers, Muxes, Proxies, and the Same Basic Shape
This problem is not unique to proxies.
A lot of tech vocabulary names similar shapes differently depending on layer, protocol, community, and historical context.
A router routes.
A mux selects.
A proxy forwards on behalf of something.
A reverse proxy receives on behalf of a service.
A load balancer distributes across eligible targets.
An API gateway receives API traffic and applies routing, authentication, policy, and other middleware.
A service mesh sidecar intercepts or mediates service-to-service traffic.
These things are not identical. They operate at different layers and have different guarantees, constraints, and conventions.
But they rhyme.
They all involve a middle layer that receives something, inspects something, and decides what happens next.
That “something” might be:
a packet
an HTTP request
a hostname
a path
a method
a header
a stream
a function call
a message
an event
And the decision might be based on:
destination address
hostname
path
method
authentication state
load
latency
availability
policy
tenant
version
region
The names change.
The shape often stays the same.
Something comes in. A middle layer decides where it goes next.
Why “Reverse Proxy” Feels Like a Bad Name
“Reverse proxy” feels like a bad name because it explains the concept by reference to another concept instead of by reference to its own function.
If you already know what a forward proxy is, then “reverse proxy” can be explained as:
Like a proxy, but controlled by the service side instead of the client side.
Fine.
But if you are learning deployment, that is not necessarily the most natural entrypoint.
In practical deployment, the thing people call a reverse proxy is often the public service front door.
It receives traffic for a hostname.
It terminates TLS.
It routes requests.
It forwards to internal services.
It may apply middleware.
It may hide the implementation details of the backend.
It may load-balance across several targets.
That component could be described more directly as:
service front door
request gateway
traffic gateway
edge router
HTTP router
ingress router
server-side proxy
controlled middle layer
authorized middlebox
Some of those names are better than others. None of them are perfect.
But they at least point toward what the component does.
“Reverse proxy” points backward toward the historical comparison.
The Point-of-View Problem
The deeper issue is that “forward” and “reverse” are not purely physical descriptions.
They depend on point of view.
Consider a public request path:
User → CDN → load balancer → ingress → app server → internal API → database
Which thing is the proxy?
The CDN might be acting as a reverse proxy for the website.
The load balancer might be acting as a reverse proxy for the application pool.
The ingress might be acting as a reverse proxy for services inside the cluster.
The app server might call an internal API, but that may or may not be proxy-like.
The database connection may go through a connection pooler, which is another kind of middle layer.
At every step, there is another possible boundary.
Inside one boundary, a component is “the public edge.”
Inside another boundary, it is just one hop among many.
Inside another boundary, it is an implementation detail.
That is why the terminology can feel unstable.
The classification depends on the question being asked.
Are we talking about the client’s relationship to the internet?
Are we talking about the service owner’s relationship to its backend processes?
Are we talking about packet routing?
Are we talking about HTTP request routing?
Are we talking about application dependencies?
Are we talking about ownership, configuration, trust, visibility, or abstraction?
The same diagram can produce different names depending on which relationship we highlight.
My Preferred Mental Model
I still use the official terms because they are the official terms.
If the industry calls something a reverse proxy, it is useful to know that term.
But when I am thinking through systems, I prefer to start with a more general model:
Something wants to reach something else.
A middle layer receives the communication.
The middle layer makes a decision.
The communication either stops there, changes there, or moves onward.
Then I ask:
Who controls the middle layer?
Which side does it represent?
What does it inspect?
What decision does it make?
What policy does it enforce?
Where can it forward the request?
Is the original caller trying to reach the final destination,
or is the middle component just making its own dependency call?
Those questions are more useful than starting with:
Is this a forward proxy or a reverse proxy?
The forward/reverse distinction can come later.
First, identify the relationship.
Then identify the boundary.
Then identify the role.
Conclusion
“Forward proxy” and “reverse proxy” are not useless terms.
They point to a real distinction:
Forward proxy:
requester-side intermediary
Reverse proxy:
service-side intermediary
But the names are worse than the concepts.
Both forward requests.
Both are middle layers.
Both can filter, route, cache, transform, log, authenticate, and mediate traffic.
The difference is not the direction of the request. The difference is the side of the relationship the proxy is associated with.
And once you zoom out into real systems, even that distinction depends on point of view.
That is why “reverse proxy” feels confusing.
The term is trying to describe a role in a communication relationship, but it sounds like it is describing a physical direction.
It is not.
It is a name inherited from a specific conceptual contrast.
The better mental model is:
Everything is a middlebox until you pick a boundary.
Once you pick the boundary, the names become more useful.
Until then, “reverse proxy” is just another reminder that tech nomenclature often preserves history better than it teaches concepts.
Comments
No comments yet. Be the first!