Almost every production site is served through these layers, and their behaviour depends on your HTTP headers.
Requests rarely go straight to your application.
A reverse proxy (nginx, HAProxy, Envoy, Caddy) accepts client connections and forwards them to backend servers. It terminates TLS, compresses responses, serves static files, enforces limits and adds headers. A load balancer is a proxy that spreads traffic across several backends using health checks.
Behind a proxy, your app sees the proxy's IP. The original client data travels in Forwarded or the de facto X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Host headers. Only trust them when set by your own proxy; clients can forge them.
A CDN (Cloudflare, Fastly, CloudFront, Akamai) runs reverse proxies in hundreds of locations, called edge servers or PoPs. Users connect to a nearby edge, which shortens TCP and TLS handshakes, and the edge serves cached responses or fetches from your origin.
The CDN cache follows your headers:
Cache-Control: public, s-maxage=600lets shared caches keep a response for 10 minutes while browsers usemax-age.privateorno-storekeeps responses with user data off the edge. Cookies andAuthorizationusually make CDNs bypass the cache by default.Varyadds headers to the cache key, e.g.Vary: Accept-Encoding.- The
Ageresponse header shows how long a copy has been cached; providers add hit/miss headers such ascf-cache-status.
Invalidating ("purging") is possible but slow and error-prone. Hashed asset URLs avoid it entirely. CDNs also absorb DDoS traffic and can run code at the edge.
Example
# Is the response served from the CDN cache?
$ curl -sI https://www.example-shop.com/assets/app.3f9a1c.js | grep -iE "cache-control|age|cache-status|x-cache"
cache-control: public, max-age=31536000, immutable
age: 48211
cf-cache-status: HIT
# nginx as a reverse proxy in front of an app on port 3000
# location / {
# 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;
# }Remember
- Reverse proxies terminate TLS and forward to backends
- Trust X-Forwarded-* only from your own proxy
- CDN edges cache by your Cache-Control (s-maxage for shared caches)
- Keep personalised responses private or no-store
Watch out for
- Caching a personalised page publicly at the CDN, so one user's data is served to others.