# Reverse Proxy

> A reverse proxy sits in front of origin servers and forwards client requests to them. Learn the headers it adds, nginx proxy_pass pitfalls and 502/504 causes.

Source: https://howhttpworks.com/glossary/reverse-proxy
Last reviewed: 2026-10-04

> **TL;DR:** A reverse proxy is the server clients actually connect to. It forwards requests to one or more backends and returns their responses, adding TLS, routing, caching or load balancing on the way.

A reverse proxy is an intermediary that sits in front of one or more origin servers and presents itself to clients as if it were the origin. nginx, HAProxy, Envoy, Caddy, Traefik and cloud load balancers all play this role. The client never sees the backend address, and the backend sees the proxy as its client.

## A typical nginx configuration

```nginx
location /api/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}
```

The backend then receives headers like these, with the real client address only available in the forwarded header:

```http
GET /api/me HTTP/1.1
Host: www.example.com
X-Forwarded-For: 203.0.113.9
X-Forwarded-Proto: https
```

## Non-obvious facts

- **nginx rewrites `Host` by default.** Without `proxy_set_header Host $host`, the upstream receives `Host: $proxy_host` (the `proxy_pass` hostname), so apps that build absolute URLs or route by virtual host misbehave.
- **Upstream connections are not kept alive by default.** nginx talks to upstreams over HTTP/1.0 and closes the connection each time. For keep-alive to a backend you need `proxy_http_version 1.1;`, `proxy_set_header Connection "";` and an `upstream` block with `keepalive`.
- **Client IP headers are spoofable.** A client can send its own `X-Forwarded-For`. Configure your app to trust only the proxy addresses or hop count you operate.
- **The proxy generates 502 and 504, not your app.** If the error page body is the proxy's, the backend never answered properly. Check the proxy error log first.
- **Proxies can cache.** A caching reverse proxy distributed across regions is a [CDN](https://howhttpworks.com/glossary/cdn).

## Go deeper

- [X-Forwarded-For](https://howhttpworks.com/headers/x-forwarded-for)
- [Forwarded header](https://howhttpworks.com/headers/forwarded)
- [Via header](https://howhttpworks.com/headers/via)
- [nginx 502 Bad Gateway](https://howhttpworks.com/debug/nginx-502-bad-gateway)
- [nginx 504 Gateway Timeout](https://howhttpworks.com/debug/nginx-504-gateway-timeout)
