Nearly every production web application sits behind a reverse proxy. nginx, Caddy, Apache, HAProxy, Cloudflare — these are the public-facing layer that receives incoming traffic and forwards it to your application. The application server only sees traffic from the reverse proxy; the public internet only sees the reverse proxy.
This post explains what a reverse proxy actually is, the responsibilities it commonly handles, and how to choose between the major options for new deployments in 2026.
Forward Proxy vs Reverse Proxy
Two related but different concepts:
Forward proxy
Sits between clients and the internet. Used by clients to access external services anonymously or through controlled paths. Corporate web filtering, anonymizing proxies, residential proxies — all are forward proxies.
Many clients → Forward proxy → Internet
Reverse proxy
Sits between the internet and your servers. Used by servers to handle incoming traffic. nginx in front of your app is a reverse proxy.
Internet → Reverse proxy → Your application servers
For most production deployments, “the proxy” you have is a reverse proxy. This post is about reverse proxies.
What a Reverse Proxy Does
The core responsibilities:
TLS termination
Decrypts HTTPS so the backend can run plaintext HTTP. Manages certificates centrally.
Request routing
Routes by hostname, path, header. Multiple services on one IP/port.
Load balancing
Distributes traffic across multiple backend instances. Health checks, failover.
Caching
Stores responses for repeated requests. Reduces backend load.
Compression
Gzip/Brotli responses before sending to clients.
Request/response modification
Add or remove headers, rewrite URLs, transform bodies.
Authentication
Basic auth, OAuth proxy, OIDC validation before backend sees the request.
Rate limiting
Limit per-IP or per-endpoint request rates.
Static file serving
Serve assets directly without hitting the application.
Logging
Centralized access logs.
That’s a lot. Most reverse proxies do most of these. The differences are in implementation quality, configuration style, and ecosystem.
The Architecture Pattern
A typical production stack:
Internet
↓
CDN (Cloudflare, Fastly) — optional outer layer
↓
Reverse proxy (nginx) — TLS termination, routing
↓
Application servers (Node, Python, etc.)
↓
Databases, caches
Each layer has a specific role. The CDN handles cache and DDoS at the edge. The reverse proxy handles TLS and routing close to the application. The application focuses on business logic.
Smaller deployments combine layers (no CDN; nginx does everything). Bigger ones add more (multiple reverse proxy layers, service mesh between services).
Major Options in 2026
nginx
The industry workhorse. Mature, fast, well-documented, extensive ecosystem.
- Strengths: stable, performant, great community, vast deployment.
- Weaknesses: configuration is C-like and quirky; reloading config sometimes drops connections; modules need recompilation.
Best for: stable production deployments where you have nginx expertise.
Caddy
Modern (since 2015), Go-based, opinionated. Built around automatic HTTPS.
- Strengths: automatic Let’s Encrypt certificates by default; clean configuration; HTTP/3 native; modular architecture.
- Weaknesses: smaller ecosystem; opinionated choices may not fit all needs.
Best for: new deployments where Let’s Encrypt + simplicity is valuable.
HAProxy
Specializes in load balancing, especially L4. Very high throughput.
- Strengths: unmatched performance for L4 workloads; rich stats; great for “I have huge throughput needs.”
- Weaknesses: weaker as a feature-rich reverse proxy; less rich L7 features than nginx.
Best for: high-throughput L4 load balancing, financial systems.
Apache (httpd)
The classic. Still around but less commonly used as a reverse proxy in 2026.
- Strengths: extremely mature; familiar to many engineers.
- Weaknesses: worse performance than nginx; complex configuration; less modern.
Best for: existing Apache shops; otherwise nginx or Caddy is usually preferred.
Envoy
Modern, designed for service mesh. C++.
- Strengths: dynamic configuration via API; observability built in; service-mesh integration.
- Weaknesses: complex to operate standalone; designed more for microservices than monolithic frontend.
Best for: Kubernetes / service-mesh deployments (Istio uses Envoy under the hood).
Traefik
Auto-discovery focused. Reads container labels / Kubernetes annotations to configure itself.
- Strengths: zero-config for Docker / K8s; auto Let’s Encrypt; modern UI.
- Weaknesses: less battle-tested than nginx; some niche features missing.
Best for: container-heavy deployments where you want minimal manual configuration.
Cloudflare (managed)
SaaS reverse proxy + CDN. Handles everything.
- Strengths: zero infra to operate; included DDoS protection; global anycast; rich edge features.
- Weaknesses: lock-in; less control than self-hosted; cost at scale.
Best for: most modern web apps. The default if you don’t have a specific reason for self-hosted.
Configuration Style Comparison
nginx
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/example.com.crt;
ssl_certificate_key /etc/ssl/example.com.key;
location / {
proxy_pass http://app:3000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
}
location /api/ {
proxy_pass http://api:3001;
# ...
}
}
Caddy
example.com {
reverse_proxy /api/* api:3001
reverse_proxy /* app:3000
}
Caddy automatically gets a TLS certificate for example.com via Let’s Encrypt.
Caddy’s configuration is dramatically simpler. nginx gives you more granular control. Pick by preference.
Common Reverse Proxy Tasks
Setting headers
Add X-Forwarded-For, X-Real-IP, X-Forwarded-Proto so the backend knows the original client IP, scheme, etc.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
Path rewriting
Map external /api/v1/users to internal /users on the backend.
location /api/v1/ {
rewrite ^/api/v1/(.*)$ /$1 break;
proxy_pass http://api:3001;
}
Static file serving
Serve assets directly without hitting the application:
location /static/ {
alias /var/www/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
Rate limiting
nginx:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://api:3001;
}
Caching responses
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=app_cache:10m max_size=1g;
location / {
proxy_cache app_cache;
proxy_cache_valid 200 5m;
proxy_pass http://app:3000;
}
CORS
Add CORS headers at the proxy layer:
add_header Access-Control-Allow-Origin "https://example.com" always;
See CORS explained.
Performance Considerations
For most workloads, performance differences between nginx/Caddy/HAProxy don’t matter — all can saturate gigabit links easily. Where it does matter:
- Connections per second at very high scale.
- Latency overhead for ultra-low-latency systems.
- Memory usage with thousands of concurrent connections.
nginx and HAProxy are typically the fastest. Caddy is modern but slightly behind on raw numbers. For 99% of production workloads, “fast enough” applies to all.
Operational Topics
Reload without dropped connections
nginx’s reload mechanism is good but has edge cases. Caddy uses zero-downtime config reloading. For production, automate config validation before reload.
Logging
Both nginx and Caddy support structured logs (JSON) suitable for log aggregation. Logs include IP, path, response code, latency.
Metrics
- nginx:
/nginx_statusendpoint with basic stats; commercial nginx Plus has richer metrics. - Caddy: Built-in Prometheus metrics.
- HAProxy: Stats page; structured metrics export.
Health checks
Backend health checks built into every major reverse proxy. See load balancer types.
When You Don’t Need a Reverse Proxy
Edge cases where a reverse proxy adds complexity without much value:
- Pure API serving with a single backend, no static files, no path-based routing. The application can listen on the public interface directly.
- Behind a managed CDN like Cloudflare that already does TLS termination and routing. The reverse proxy layer adds redundancy.
- Small internal services with no public exposure.
But for any production web app serving the internet: reverse proxy is the default. Don’t expose your app server directly.
TL;DR
- Reverse proxy sits between the internet and your application.
- Responsibilities: TLS, routing, load balancing, caching, headers, rate limiting.
- nginx is the industry standard.
- Caddy is the modern, automatic-HTTPS alternative.
- HAProxy specializes in high-throughput load balancing.
- Envoy is for service-mesh / dynamic-config environments.
- Cloudflare is the managed alternative; default for many modern deployments.
- Configuration patterns include setting forwarded-for headers, path rewriting, static serving, rate limiting.
A reverse proxy is one of those infrastructure choices that’s hard to get wrong: any of the major options work for most workloads. The choice is mostly about ecosystem fit (nginx for stability, Caddy for simplicity, Cloudflare for managed). For the load-balancer aspect specifically, see load balancer types; for what the proxy hands off to the backend, X-Forwarded-For header.