Reverse proxy (vs load balancer)

A reverse proxy is a server that sits in front of your backends, accepting client requests on their behalf and forwarding them — a single front door that can also cache, terminate TLS, and hide topology.

Why it matters

It gives you one place to do cross-cutting work that you’d otherwise duplicate in every service: TLS termination, compression, caching, request buffering, rate limiting, and a stable public endpoint while backends churn behind it. It also improves security and operability — clients never see internal hostnames, ports, or how many instances exist. Nginx, Envoy, HAProxy, and Caddy are the usual tools.

How it works

A forward proxy fronts clients (an outbound corporate proxy); a reverse proxy fronts servers. Where a load balancer’s job is distributing across many backends, a reverse proxy’s job is being the front door — and the two overlap heavily because most L7 load balancers are reverse proxies, and most reverse proxies can balance load. Think of it by intent, not product:

CapabilityReverse proxyLoad balancer
Single entry pointcore purposeside effect
Spread across backendsoptionalcore purpose
Caching / compressioncommonrare
TLS terminationyesL7 yes

A useful framing: load balancing is one feature a reverse proxy may offer. You’d still want a reverse proxy in front of a single backend — for TLS, caching, and buffering — where a load balancer alone makes no sense. Layer more behavior on top and it becomes an API gateway; pin a cache to it and it overlaps a CDN edge.

Example

Nginx as a reverse proxy in front of one app server:

client ──TLS──▶ nginx :443
                 ├─ terminate TLS, gzip response
                 ├─ serve /static/* from local cache (HIT)
                 └─ proxy_pass /api/* ──HTTP──▶ app:8080

Internal app:8080 is never exposed; swap or scale it without clients noticing.

Pitfalls

  • Forgetting X-Forwarded-For/-Proto. The backend sees the proxy’s IP and thinks every request is plaintext; pass and trust these headers correctly.
  • Buffering large uploads/streams. Default request buffering can stall big uploads or SSE; tune or disable per route.
  • Treating it as the LB’s redundancy story. A lone reverse proxy is still a SPOF — it needs its own active-passive/active-active setup.
  • Mismatched timeouts. Proxy and backend timeouts that disagree produce confusing 502/504s under load.

See also