A reverse proxy is a server that sits in front of your application servers and forwards client requests to them. From the client's perspective, they're talking to one server — the proxy — but behind the scenes, requests are being routed to multiple servers or services.
Forward Proxy vs Reverse Proxy
| Forward Proxy | Reverse Proxy | |
|---|---|---|
| Sits in front of | Clients | Servers |
| Hides | Client identity from server | Server identity from client |
| Used for | Privacy, content filtering, corporate networks | Load balancing, SSL termination, caching |
| Example | VPN, Squid proxy | Nginx, Cloudflare, AWS ALB |
What a Reverse Proxy Does
- SSL termination — handle TLS decryption so your app doesn't need to. Your Node.js or Python app receives plain HTTP, Nginx handles the SSL complexity.
- Load balancing — distribute traffic across multiple application servers.
- Caching — cache responses from application servers to reduce backend load.
- Compression — gzip responses before sending to clients.
- Security — hide your backend architecture, filter malicious requests, rate limiting.
- Single entry point — route different URL paths to different backend services.
Nginx as Reverse Proxy
# Route all requests to a Node.js app on port 3000
server {
listen 443 ssl;
server_name api.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# Route different paths to different services
server {
listen 443 ssl;
server_name example.com;
location /api/ {
proxy_pass http://localhost:3000; # API service
}
location /uploads/ {
root /var/www/storage; # Static files served directly
}
location / {
proxy_pass http://localhost:3001; # Frontend service
}
}Why Every Production App Uses One
Running your Node.js or Python app directly on port 80/443 means it handles SSL, compression, and static files itself — work it's not optimized for. Nginx handles these concerns 10-100x more efficiently, freeing your app to focus on business logic. It also means you can restart your app without dropping connections — Nginx buffers requests while your app restarts.