Reverse Proxy Explained: Nginx, Load Balancing, SSL & Security 2026

Reverse Proxy Explained: Nginx, Load Balancing, SSL, Caching and Security

Modern web applications rarely expose their application servers directly to the public internet.

A production request commonly passes through several infrastructure layers before reaching the code responsible for generating a response:

Internet
   │
   ▼
DNS
   │
   ▼
CDN / Edge Network
   │
   ▼
Reverse Proxy
   │
   ▼
Load Balancing
   │
   ├── Application Server 1
   ├── Application Server 2
   └── Application Server 3

One of the most important components in this architecture is the reverse proxy.

A reverse proxy accepts requests on behalf of backend services and decides where those requests should go. In production environments, however, its responsibilities can extend far beyond forwarding traffic.

Reverse proxies can participate in TLS termination, application routing, load balancing, caching, compression, WebSocket proxying, rate limiting, authentication, security-header enforcement, request filtering, observability, and backend isolation.

Technologies such as Nginx, HAProxy, Traefik, and Caddy can implement different parts of this architecture.

Understanding reverse proxies is therefore essential for system administrators, network engineers, DevOps engineers, cloud architects, and developers working with APIs, containers, microservices, Kubernetes, Linux servers, or distributed applications.

This guide explains reverse proxy architecture from the network layer to production deployment, including Nginx configuration, TLS termination, load balancing, caching, headers, WebSockets, containers, microservices, security, high availability, observability, and troubleshooting.

For the infrastructure layer that frequently sits in front of a reverse proxy, read CDN Caching Explained. For the broader server architecture behind it, see Servers and Infrastructure Explained.

What Is a Reverse Proxy?

A reverse proxy is an intermediary server positioned between clients and backend application servers.

Without one:

Client
   │
   ▼
Application Server

With a reverse proxy:

Client
   │
   ▼
Reverse Proxy
   │
   ▼
Application Server

The client communicates with the reverse proxy.

The proxy communicates with the backend.

For example, users might access:

https://example.com

while the application itself listens internally at:

10.0.10.25:3000

The request path becomes:

Internet
   │
   ▼
example.com:443
   │
   ▼
Reverse Proxy
   │
   ▼
10.0.10.25:3000

The internal application server does not need to be directly accessible from the public internet.

This creates an important architectural boundary between:

PUBLIC NETWORK

and:

APPLICATION NETWORK

Why Reverse Proxies Exist

Consider an application containing several services:

Frontend
API
Authentication
Admin Panel
Monitoring Dashboard

Without a reverse proxy, administrators might expose multiple services directly:

example.com:3000
example.com:4000
example.com:5000
example.com:6000

This becomes difficult to manage and expands the externally exposed attack surface.

A reverse proxy creates a single controlled entry point:

                    Internet
                       │
                       ▼
                  Reverse Proxy
                       │
         ┌─────────────┼─────────────┐
         ▼             ▼             ▼
      Frontend        API          Admin
       :3000          :4000         :5000

Users can instead access clean URLs:

example.com/
example.com/api/
admin.example.com/

while internal services remain on private addresses and ports.

This separation improves:

  • architecture;
  • routing;
  • security;
  • certificate management;
  • scalability;
  • observability;
  • maintainability.

Reverse Proxy vs Forward Proxy

Reverse proxies and forward proxies are often confused.

A forward proxy represents clients.

Clients
   │
   ▼
Forward Proxy
   │
   ▼
Internet

External servers communicate with the proxy rather than directly with each internal client.

Forward proxies can be used for:

  • outbound internet control;
  • privacy;
  • content filtering;
  • corporate access policies;
  • logging;
  • network restrictions.

A reverse proxy represents servers.

Internet
   │
   ▼
Reverse Proxy
   │
   ▼
Backend Servers

The user communicates with the proxy without necessarily knowing which backend system processes the request.

A useful mental model is:

Forward Proxy
Client → Proxy → Internet
        ↑
   Represents clients

while:

Reverse Proxy
Internet → Proxy → Servers
           ↑
      Represents servers

Reverse Proxy vs Load Balancer

Reverse proxying and load balancing overlap, but they describe different architectural responsibilities.

A basic reverse proxy can forward traffic to one backend:

Client
   │
   ▼
Reverse Proxy
   │
   ▼
Application

A reverse proxy can also distribute traffic among several servers:

                 Reverse Proxy
                      │
          ┌───────────┼───────────┐
          ▼           ▼           ▼
       Server A    Server B    Server C

This introduces load balancing.

Therefore technologies such as Nginx can act as:

Reverse Proxy
+
Load Balancer

Reverse proxying describes the intermediary role.

Load balancing describes the distribution of workloads.

For a deeper explanation of traffic distribution, see Cloud Load Balancing Explained.


How Reverse Proxying Works

Suppose a user requests:

https://example.com/products

DNS resolves the hostname:

example.com
     │
     ▼
203.0.113.20

That address belongs to the public-facing infrastructure.

The request arrives at the reverse proxy:

Browser
   │
   ▼
Reverse Proxy

The proxy examines information such as:

Hostname
URL Path
HTTP Method
Headers
Cookies
Routing Rules

and selects a backend:

/products
     │
     ▼
10.0.10.25:8080

The backend processes the request:

Reverse Proxy
     │
     ▼
Backend
     │
     ▼
Application Logic
     │
     ▼
Database

The response returns through the proxy:

Database
   │
   ▼
Application
   │
   ▼
Reverse Proxy
   │
   ▼
Browser

From the client’s perspective, communication happened with:

example.com

not with:

10.0.10.25

Nginx as a Reverse Proxy

Nginx is widely used as a web server, reverse proxy, HTTP cache, and load balancer.

A simple architecture might be:

Internet
   │
   ▼
Nginx
   │
   ▼
Node.js

The Node.js application listens locally:

127.0.0.1:3000

while Nginx accepts external HTTP traffic.

A minimal configuration could look like:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

The application remains on port 3000.

Users communicate through standard HTTP port 80.

In production, HTTPS normally replaces plain HTTP for the public connection.


Understanding proxy_pass

The Nginx directive:

proxy_pass

defines where matching requests should be forwarded.

Example:

location / {
    proxy_pass http://127.0.0.1:3000;
}

produces:

Browser
   │
   ▼
Nginx :80/:443
   │
   ▼
Application :3000

The backend could also exist on another server:

proxy_pass http://10.0.20.15:8080;

or be represented by an upstream group:

upstream backend {
    server 10.0.20.11:8080;
    server 10.0.20.12:8080;
}

followed by:

location / {
    proxy_pass http://backend;
}

Now the proxy can distribute requests across multiple application instances.

The official Nginx reverse proxy documentation explains the proxy directives and request-forwarding model in more detail.


Preserving Client Information

When a reverse proxy connects to a backend, the backend sees the proxy as its immediate network peer.

Without additional information:

Client
  │
  ▼
Proxy
  │
  ▼
Backend

the backend may identify the proxy address instead of the original client.

Important forwarding headers therefore commonly include:

Host
X-Real-IP
X-Forwarded-For
X-Forwarded-Proto

A typical Nginx configuration is:

location / {
    proxy_pass http://127.0.0.1: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;
}

This allows the backend to understand the original request context.


Why X-Forwarded-For Matters

Consider:

Client: 198.51.100.50
Proxy: 10.0.0.5
Backend: 10.0.0.10

At the TCP layer, the backend receives a connection from:

10.0.0.5

Without forwarding information, application logs may record every visitor as the proxy.

X-Forwarded-For can preserve the original client chain.

Conceptually:

X-Forwarded-For: 198.51.100.50

In architectures containing multiple proxies:

Client
  │
  ▼
CDN
  │
  ▼
Load Balancer
  │
  ▼
Reverse Proxy

the chain becomes more complicated.

Applications should trust forwarded headers only from known proxy infrastructure because arbitrary internet clients can otherwise attempt to spoof them.


X-Forwarded-Proto

Another important header is:

X-Forwarded-Proto

Suppose:

Browser
   │ HTTPS
   ▼
Reverse Proxy
   │ HTTP
   ▼
Backend

The backend’s direct connection is HTTP.

But the original client used HTTPS.

Without forwarded protocol information, the application may incorrectly believe the user accessed:

http://example.com

This can cause:

  • incorrect redirects;
  • wrong canonical URLs;
  • insecure cookie behavior;
  • redirect loops.

The proxy can forward:

X-Forwarded-Proto: https

so the application knows the original connection was encrypted.


Host-Based Routing

A reverse proxy can route requests according to the hostname.

Suppose:

app.example.com
api.example.com
admin.example.com

all point to one public reverse proxy.

The architecture becomes:

                   Reverse Proxy
                         │
          ┌──────────────┼──────────────┐
          ▼              ▼              ▼
     app.example     api.example    admin.example
          │              │              │
          ▼              ▼              ▼
      Frontend           API           Admin

Nginx can implement this using separate server blocks.

Example:

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:4000;
    }
}

This lets several applications share the same public server.


Path-Based Routing

Routing can also depend on URL paths.

Example:

example.com/
        │
        └── Frontend

example.com/api/
        │
        └── API

example.com/media/
        │
        └── Media Service

Nginx:

location / {
    proxy_pass http://frontend;
}

location /api/ {
    proxy_pass http://api;
}

location /media/ {
    proxy_pass http://media;
}

This is particularly useful for microservices.


Reverse Proxy and TLS Termination

One of the most important reverse proxy responsibilities is TLS termination.

Without termination at the proxy:

Client
   │ HTTPS
   ▼
Application Server

every application server needs to manage TLS.

With centralized TLS termination:

Client
   │ HTTPS
   ▼
Reverse Proxy
   │
   │ HTTP or HTTPS
   ▼
Backend

The reverse proxy handles:

TLS Handshake
Certificates
Cipher Negotiation
HTTPS

while backend services can use internal HTTP or re-encrypted HTTPS depending on security requirements.


Why Centralized TLS Helps

Imagine ten application servers.

Without centralized termination:

Server 1 → Certificate
Server 2 → Certificate
Server 3 → Certificate
...
Server 10 → Certificate

With a reverse proxy:

                    Certificate
                         │
                         ▼
                    Reverse Proxy
                         │
            ┌────────────┼────────────┐
            ▼            ▼            ▼
         Backend      Backend      Backend

Certificate management becomes significantly easier.

For public production services, certificate automation should generally be preferred over manual certificate replacement.


HTTPS Redirect

A common configuration redirects HTTP to HTTPS:

server {
    listen 80;
    server_name example.com;

    return 301 https://$host$request_uri;
}

Then HTTPS traffic is handled separately:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/fullchain.pem;
    ssl_certificate_key /path/privkey.pem;

    location / {
        proxy_pass http://backend;
    }
}

Exact TLS configuration should follow current security guidance rather than copied legacy configurations.


TLS Termination vs TLS Passthrough

TLS termination:

Client
   │ HTTPS
   ▼
Proxy
   │
   ▼
Decrypt
   │
   ▼
Backend

TLS passthrough:

Client
   │ HTTPS
   ▼
Proxy
   │ Encrypted
   ▼
Backend

Termination gives the proxy access to HTTP information, enabling:

Path Routing
Header Manipulation
HTTP Caching
Application-Level Security

Passthrough preserves end-to-end encryption to the backend but limits application-layer inspection at that proxy layer.


Re-Encryption

A third pattern is:

Client
   │ HTTPS
   ▼
Reverse Proxy
   │
   │ HTTPS
   ▼
Backend

The proxy terminates the client TLS connection and creates another TLS connection to the backend.

This can be useful when internal security requirements demand encryption between infrastructure components.


Reverse Proxy Load Balancing

A reverse proxy can distribute traffic among backend servers.

Example:

upstream application {
    server 10.0.10.11:8080;
    server 10.0.10.12:8080;
    server 10.0.10.13:8080;
}

server {
    listen 80;

    location / {
        proxy_pass http://application;
    }
}

Architecture:

                   Nginx
                     │
        ┌────────────┼────────────┐
        ▼            ▼            ▼
     App 1         App 2         App 3

This enables horizontal scaling.


Round Robin

A common distribution model is conceptually:

Request 1 → Server A
Request 2 → Server B
Request 3 → Server C
Request 4 → Server A

This works well when servers have similar capacity and requests have roughly comparable cost.


Least Connections

Some workloads contain long-running requests.

For those systems, simply rotating requests may not provide balanced utilization.

Least-connections routing prefers the backend with fewer active connections.

Conceptually:

Server A → 100 connections
Server B → 20 connections
Server C → 60 connections

New request:

→ Server B

Nginx supports several upstream load-balancing methods, documented in its HTTP load balancing guide.


Weighted Load Balancing

Not every server has equal capacity.

Suppose:

Server A = 16 CPU cores
Server B = 8 CPU cores

Traffic can be weighted so that Server A receives a larger proportion.

Conceptually:

Server A → weight 2
Server B → weight 1

This is useful during:

  • heterogeneous infrastructure;
  • migrations;
  • capacity expansion;
  • gradual rollouts.

Session Persistence

Some applications store session state locally.

Suppose:

Login
  │
  ▼
Server A

creates local session data.

If the next request reaches:

Server B

the session may disappear.

This creates pressure for sticky sessions:

User A → Server A
User A → Server A
User A → Server A

But a more scalable architecture often externalizes state:

                 Servers
            ┌──────┼──────┐
            ▼      ▼      ▼
            A      B      C
             \     │     /
              \    │    /
               ▼   ▼   ▼
              Shared Session Store

This allows any backend instance to process the request.

Stateless application design generally improves horizontal scalability.


Backend Failure

Suppose:

Server A = Healthy
Server B = Failed
Server C = Healthy

The proxy should avoid repeatedly sending traffic to Server B.

A resilient architecture requires backend failure detection and appropriate retry behavior.

Conceptually:

Reverse Proxy
     │
     ├── A ✓
     ├── B ✗
     └── C ✓

Traffic continues through healthy systems.

The exact health-check capabilities depend on the proxy product and edition, so production configurations should be verified against the relevant official documentation.


Reverse Proxy Caching

A reverse proxy can also cache responses.

Without caching:

Request
   │
   ▼
Nginx
   │
   ▼
Application
   │
   ▼
Database

With caching:

Request
   │
   ▼
Nginx Cache
   │
   ├── HIT ─────► Response
   │
   └── MISS
       │
       ▼
   Application

This can reduce backend load substantially.

Nginx provides HTTP caching functionality documented in its content caching guide.


Reverse Proxy Cache vs CDN Cache

These layers are related but not identical.

A CDN cache is usually geographically distributed:

Global Users
     │
     ▼
Global CDN

A reverse proxy cache commonly exists close to the origin:

CDN
 │
 ▼
Reverse Proxy Cache
 │
 ▼
Application

A production architecture may therefore contain both:

User
 │
 ▼
CDN Cache
 │
 ▼
Reverse Proxy Cache
 │
 ▼
Application
 │
 ▼
Database

Each cache protects the layer behind it.

For detailed TTL, Cache-Control, cache-key, HIT/MISS, and invalidation concepts, see CDN Caching Explained.


Cache Hierarchy

A complete web application may contain:

Browser Cache
     │
     ▼
CDN Cache
     │
     ▼
Reverse Proxy Cache
     │
     ▼
Application Cache
     │
     ▼
Redis
     │
     ▼
Database

This architecture can be extremely efficient.

It can also become extremely confusing if nobody knows which layer owns freshness.

A production caching strategy should document:

What is cached?
Where?
For how long?
How is it invalidated?
Which headers control it?

Without those answers, stale-data incidents become difficult to diagnose.


Reverse Proxy Compression

Reverse proxies can compress HTTP responses before sending them to clients.

For example:

Application
   │
   │ Large Response
   ▼
Nginx
   │
   ▼
Compression
   │
   ▼
Smaller Response

Compression can reduce transferred bytes for suitable content types such as:

HTML
CSS
JavaScript
JSON
SVG

But already-compressed formats such as many image, video, and archive formats usually provide little additional benefit.

Compression also consumes CPU, so configuration should reflect actual workloads.


WebSocket Reverse Proxy

Traditional HTTP often follows:

Request
   │
   ▼
Response

WebSockets create long-lived bidirectional connections:

Client
   ⇅
WebSocket
   ⇅
Server

When a reverse proxy sits between them:

Client
   ⇅
Reverse Proxy
   ⇅
WebSocket Server

the proxy must correctly handle the protocol upgrade.

A common Nginx pattern includes:

location /socket/ {
    proxy_pass http://websocket_backend;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

The official Nginx documentation covers WebSocket proxying.

This is relevant to:

  • chat applications;
  • dashboards;
  • multiplayer systems;
  • real-time notifications;
  • collaborative applications.

Reverse Proxy Security

A reverse proxy is not automatically a firewall, but it can become an important security-control point.

Architecture:

Internet
   │
   ▼
Reverse Proxy
   │
   ├── TLS
   ├── Request Validation
   ├── Rate Limiting
   ├── Header Policies
   └── Routing
   │
   ▼
Backend

This provides a controlled boundary before requests reach application servers.

For broader network-security concepts, see Network Security Basics and Firewalls Explained.


Hide Backend Servers

One important design principle is:

Internet
   │
   ▼
Reverse Proxy
   │
   ▼
Private Backend Network

rather than:

Internet
   ├── Reverse Proxy
   ├── Backend 1
   ├── Backend 2
   └── Database

Backend services should generally expose only the network interfaces and ports required for their role.

For example:

Internet
   │
   ▼
Firewall
   │
   ▼
Reverse Proxy :443
   │
   ▼
Private Application Network

The database should not become publicly accessible merely because the application uses it.


Reverse Proxy Is Not a Security Boundary by Itself

Hiding a backend address does not make the backend secure.

You still need:

Firewall Rules
Authentication
Authorization
Patching
TLS where required
Network Segmentation
Least Privilege
Monitoring

A reverse proxy is one security layer—not a replacement for defense in depth.


Rate Limiting

A reverse proxy can restrict request frequency before traffic reaches the application.

Without rate limiting:

Client
  │
  ├── Request
  ├── Request
  ├── Request
  ├── Request
  └── Request × 10000
          │
          ▼
      Application

With rate limiting:

Client
   │
   ▼
Reverse Proxy
   │
   ├── Allowed
   └── Excessive → Reject / Delay

This can protect:

  • login endpoints;
  • APIs;
  • expensive searches;
  • password-reset endpoints;
  • resource-intensive operations.

Nginx provides request-rate controls through its limit_req module.


Example Nginx Rate Limit

A simplified example:

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
    location /api/ {
        limit_req zone=api_limit burst=20;
        proxy_pass http://api_backend;
    }
}

Conceptually:

Client
  │
  ▼
10 requests/sec policy
  │
  ├── Within Limit → Backend
  └── Excessive → Limited

Actual values should be determined from application behavior, legitimate traffic patterns, and security requirements.

Arbitrarily low limits can block real users.


Security Headers

A reverse proxy can centralize HTTP security headers.

Examples include:

Strict-Transport-Security
X-Content-Type-Options
Content-Security-Policy
Referrer-Policy

Conceptually:

Application
   │
   ▼
Reverse Proxy
   │
   ▼
Add Security Headers
   │
   ▼
Browser

This can create consistent policy across several backend services.

However, complex policies such as Content Security Policy should be designed according to the application’s actual resource requirements rather than copied blindly.


Request Size Limits

Reverse proxies can limit request sizes.

This helps prevent unexpectedly large uploads from reaching application infrastructure.

For example:

client_max_body_size 10m;

can limit accepted request-body size for an applicable Nginx context.

But the correct limit depends on application requirements.

An API accepting profile images has different requirements from a video-upload service.


Authentication Gateway

A reverse proxy can also participate in authentication architecture.

Conceptually:

User
 │
 ▼
Reverse Proxy
 │
 ▼
Authentication Check
 │
 ├── Failed → 401 / Login
 │
 └── Valid
       │
       ▼
    Backend

This is useful for:

  • internal dashboards;
  • development environments;
  • administration interfaces;
  • protected tools.

However, backend applications containing sensitive authorization logic should not blindly assume that every request arriving from the proxy is automatically authorized.


Reverse Proxy and Docker

Containers make reverse proxies especially useful.

Imagine:

Container A → Frontend :3000
Container B → API :4000
Container C → Auth :5000

These internal ports do not all need to be exposed publicly.

Instead:

                  Internet
                     │
                     ▼
               Reverse Proxy
                     │
        ┌────────────┼────────────┐
        ▼            ▼            ▼
    Frontend        API          Auth
   Container     Container     Container

The proxy becomes the application’s public gateway.


Docker Network Architecture

A Docker deployment might use:

Public Network
     │
     ▼
Reverse Proxy Container
     │
     ▼
Private Docker Network
     │
     ├── frontend
     ├── api
     └── database

Only the reverse proxy exposes:

80
443

while application services communicate through the internal container network.

This is generally cleaner than exposing every service directly to the host network.


Reverse Proxy and Microservices

Microservices increase routing complexity.

Suppose an application contains:

User Service
Order Service
Payment Service
Search Service
Notification Service

A proxy or gateway can route:

/api/users/*     → User Service
/api/orders/*    → Order Service
/api/payments/*  → Payment Service
/api/search/*    → Search Service

Architecture:

                        Client
                          │
                          ▼
                     Proxy/Gateway
                          │
          ┌───────────────┼────────────────┐
          ▼               ▼                ▼
        Users           Orders          Search
          │               │                │
          ▼               ▼                ▼
       Service         Service          Service

As the architecture becomes more complex, however, the distinction between:

Reverse Proxy
API Gateway
Ingress Controller
Service Mesh

becomes increasingly important.

They overlap, but they are not identical.


Reverse Proxy vs API Gateway

A reverse proxy focuses primarily on traffic forwarding and application delivery.

An API gateway may add API-specific capabilities such as:

Authentication
API Keys
Quotas
Request Transformation
API Analytics
Developer Policies
Version Routing

Conceptually:

Reverse Proxy
     │
     └── Where should this HTTP request go?

while an API gateway may ask:

Who is calling?
Are they authorized?
Which API plan applies?
Has the quota been exceeded?
Which version should process the request?

Some products can perform both roles.


Reverse Proxy and Kubernetes

Kubernetes applications introduce another traffic-routing layer.

A simplified architecture is:

Internet
   │
   ▼
Load Balancer
   │
   ▼
Ingress / Gateway
   │
   ▼
Kubernetes Service
   │
   ▼
Pods

Historically, Nginx has frequently been used as part of Kubernetes ingress architectures.

The underlying principle remains similar:

External Traffic
      │
      ▼
Controlled Entry Point
      │
      ▼
Routing
      │
      ▼
Internal Services

Kubernetes adds orchestration and dynamic service discovery around that model.


Reverse Proxy and Service Discovery

Static infrastructure might configure:

10.0.10.11
10.0.10.12
10.0.10.13

manually.

Container orchestration environments are more dynamic:

Container Starts
Container Stops
IP Changes
New Instance Created

This creates a need for service discovery.

Instead of routing to a permanently fixed address:

10.0.10.11

the proxy architecture can integrate with a system that identifies currently available service instances.

This is one reason products designed for dynamic environments, such as Traefik, are frequently associated with containerized deployments.


CDN + Reverse Proxy Architecture

A very common production design is:

Internet
   │
   ▼
CDN
   │
   ▼
Reverse Proxy
   │
   ▼
Application

The CDN handles:

Global Distribution
Edge Caching
Traffic Absorption
Potential Edge Security

The reverse proxy handles:

Origin Routing
TLS architecture
Backend Selection
Local Caching
Application Policies

The application handles:

Business Logic
Data Processing
Database Access

This separation creates clearer infrastructure responsibilities.


Cloudflare + Nginx Architecture

A common example is:

Visitor
   │
   ▼
Cloudflare
   │
   ▼
Nginx
   │
   ▼
WordPress / Node.js / Application
   │
   ▼
Database

The request crosses multiple proxy layers.

That means client-IP handling must be configured carefully.

Otherwise, Nginx may record Cloudflare’s proxy address instead of the actual visitor.

Cloudflare documents the visitor-IP headers used for proxied traffic in its HTTP request headers documentation.

Only trusted proxy networks should be allowed to influence the reconstructed client address.


CDN Caching + Reverse Proxy Caching

A more advanced architecture is:

User
 │
 ▼
CDN Cache
 │
 ├── HIT → Response
 │
 └── MISS
      │
      ▼
 Reverse Proxy Cache
      │
      ├── HIT → Response
      │
      └── MISS
           │
           ▼
      Application

This provides multiple levels of origin protection.

But it also creates multiple TTLs:

Browser TTL
CDN TTL
Reverse Proxy TTL
Application Cache TTL

Poor coordination can produce confusing stale-content behavior.

For the cache-control layer, refer to CDN Caching Explained.


Reverse Proxy and High Availability

A single reverse proxy can become a single point of failure.

Architecture:

Internet
   │
   ▼
Reverse Proxy
   │
   X
   │
Application

If the proxy fails, the backend may remain healthy but unreachable.

Production systems may therefore deploy redundant proxy instances:

                    Traffic Entry
                         │
               ┌─────────┴─────────┐
               ▼                   ▼
          Reverse Proxy A     Reverse Proxy B
               │                   │
               └─────────┬─────────┘
                         ▼
                   Backend Pool

The public entry layer might be implemented using:

  • cloud load balancing;
  • floating/virtual IP mechanisms;
  • managed network appliances;
  • other high-availability designs.

The exact solution depends on environment and failure requirements.


Reverse Proxy Failure Domains

High availability requires more than adding a second server.

Ask:

Are both proxies in the same VM host?

Same rack?

Same availability zone?

Same network?

Same cloud region?

Two proxy processes running on the same physical failure domain do not provide protection against that domain failing.

True availability architecture identifies independent failure boundaries.

This principle is explored more broadly in Servers and Infrastructure Explained.


Logging

A reverse proxy is an excellent observation point because almost every application request passes through it.

Logs can record:

Client IP
Timestamp
HTTP Method
URI
Status Code
Response Size
User Agent
Referer
Request Duration
Upstream Address
Upstream Response Time

Conceptually:

Internet
   │
   ▼
Reverse Proxy
   │
   ├── Access Log
   └── Error Log
   │
   ▼
Backend

These logs can help distinguish application problems from network or proxy problems.


Important Reverse Proxy Metrics

Production monitoring should consider metrics such as:

Requests per Second
Active Connections
HTTP 2xx
HTTP 3xx
HTTP 4xx
HTTP 5xx
Request Latency
Upstream Latency
Connection Errors
Backend Availability
Cache HIT Ratio
TLS Errors

Monitoring only CPU usage is not sufficient.

A proxy with low CPU can still be experiencing:

Backend Timeouts
Connection Exhaustion
DNS Failures
TLS Errors

Request Correlation

Complex architectures may include:

CDN
 ↓
Reverse Proxy
 ↓
API Gateway
 ↓
Service A
 ↓
Service B
 ↓
Database

Troubleshooting becomes much easier when a request identifier travels through the entire chain.

Example:

X-Request-ID: 8ab71c

Logs can then show:

CDN            → 8ab71c
Reverse Proxy  → 8ab71c
API            → 8ab71c
Service        → 8ab71c

This allows engineers to reconstruct the path of one failing request across distributed infrastructure.


Understanding 502 Bad Gateway

One of the most common reverse-proxy errors is:

502 Bad Gateway

Conceptually:

Client
   │
   ▼
Reverse Proxy ✓
   │
   ▼
Backend ✗

The proxy is reachable, but something went wrong while communicating with the upstream service.

Possible causes include:

Application stopped
Wrong backend port
Connection refused
Backend crash
Protocol mismatch
DNS resolution failure
TLS problem to upstream
Malformed upstream response

A 502 is therefore often an upstream communication problem, not proof that the reverse proxy itself is down.


Troubleshooting 502 Bad Gateway

Start by testing the backend directly from the proxy host.

Example:

curl http://127.0.0.1:3000

or:

curl http://10.0.10.25:8080

If this fails:

Reverse Proxy
      │
      X
   Backend

investigate the application or network path.

Check listening ports:

ss -lntp

Check Nginx configuration:

nginx -t

Inspect service state:

systemctl status nginx

and application service status as appropriate.

Review logs:

journalctl -u nginx

plus the configured Nginx error log and application logs.

For broader Linux administration techniques, see Linux Server Administration.


Understanding 503 Service Unavailable

A:

503 Service Unavailable

often indicates that a service cannot currently process the request.

Possible scenarios include:

No healthy backends
Application overloaded
Maintenance mode
Connection limits reached
Rate/capacity constraints

Architecture:

Proxy
 │
 ├── Backend A ✗
 ├── Backend B ✗
 └── Backend C ✗

The proxy may have nowhere healthy to send the request.


Understanding 504 Gateway Timeout

A:

504 Gateway Timeout

commonly indicates that the proxy waited too long for an upstream response.

Architecture:

Client
   │
   ▼
Reverse Proxy
   │
   ▼
Backend
   │
   ...
   │
   ...
   │
 TIMEOUT

Potential causes include:

  • slow database queries;
  • external API delays;
  • application deadlocks;
  • overloaded servers;
  • network problems;
  • inappropriate timeout values.

Simply increasing the proxy timeout can hide the symptom without solving the underlying performance problem.


Troubleshooting 504 Errors

Break the request path into layers:

Client
 ↓
Proxy
 ↓
Application
 ↓
Database
 ↓
External API

Measure each one.

For example:

Proxy → Application = 5 ms
Application → Database = 8 seconds

The reverse proxy is not the actual bottleneck.

Observability must follow the complete request path.


Test the Proxy with curl

Basic headers:

curl -I https://example.com

Verbose request:

curl -v https://example.com

Measure timing:

curl -o /dev/null -s \
  -w "connect=%{time_connect}\nstarttransfer=%{time_starttransfer}\ntotal=%{time_total}\n" \
  https://example.com

This can help separate:

Connection Time
Time to First Byte
Total Time

For additional command-line diagnostics, see the Linux Network Tools Guide.


Check DNS

If the hostname is incorrect, the request may never reach the expected proxy.

Use:

dig example.com

or:

dig +short example.com

For DNS fundamentals, see DNS Explained.


Check Connectivity

Test whether a backend port is reachable:

nc -vz 10.0.10.25 8080

or where appropriate:

curl -v http://10.0.10.25:8080/

This helps distinguish:

Application Problem

from:

Network Problem

Check the Linux Routing Table

For multi-interface servers:

ip route

may reveal incorrect routing.

More complex servers can require policy-based routing.

For those environments, see Linux Policy Routing with ip rule and Multiple Routing Tables.


Check Firewall Rules

A service may be running correctly but blocked by a firewall.

The path may look like:

Reverse Proxy
     │
     ▼
Firewall
     X
     │
Backend

Do not disable security controls blindly.

Instead verify that only the required source, destination, protocol, and port are permitted.

For network-security fundamentals, see Firewalls Explained.


Reverse Proxy Performance

A reverse proxy adds another network hop:

Client
 ↓
Proxy
 ↓
Backend

but it can still improve overall performance through:

Caching
Compression
Connection Reuse
Load Distribution
TLS Offload
Static Content Delivery

The relevant metric is not:

Did we add another server?

It is:

Did the complete request path become faster, more scalable, or more resilient?


Connection Reuse

Repeatedly creating backend connections can introduce overhead.

Reverse proxies can maintain and reuse upstream connections where appropriate.

Conceptually:

Request 1 ─┐
Request 2 ─┼──► Existing Backend Connection
Request 3 ─┘

rather than:

Request 1 → New Connection
Request 2 → New Connection
Request 3 → New Connection

This becomes particularly useful at high request volumes.


Static Files vs Dynamic Requests

A reverse proxy/web server can sometimes serve static assets directly:

Request
   │
   ▼
Nginx
   │
   ├── /assets/* → Static File
   │
   └── /api/*    → Application

This prevents application runtimes from handling requests that require no business logic.

Modern CDN architectures often push static delivery even further toward the edge.


Reverse Proxy and Edge Computing

The relationship can be represented as:

User
 │
 ▼
Edge
 │
 ▼
CDN
 │
 ▼
Reverse Proxy
 │
 ▼
Application

Each layer solves a different problem.

Edge computing can execute selected logic close to users.

CDN caching prevents unnecessary origin requests.

Reverse proxying controls access to application infrastructure.

Load balancing distributes requests among backends.

Applications execute business logic.

For the distributed execution layer, see Edge Computing Explained.


Reverse Proxy and Cloud Architecture

In cloud environments, a reverse proxy may exist behind managed infrastructure.

Example:

Internet
   │
   ▼
Cloud CDN
   │
   ▼
Managed Load Balancer
   │
   ▼
Nginx
   │
   ▼
Application

But not every architecture requires all layers.

For example:

Cloud Load Balancer
        │
        ▼
Application

may already provide enough functionality.

Adding Nginx only because “production architectures use Nginx” creates unnecessary complexity.

Every layer should have a defined responsibility.


Avoid Redundant Infrastructure

A poor design can become:

CDN
 ↓
Load Balancer
 ↓
Reverse Proxy
 ↓
Another Reverse Proxy
 ↓
API Gateway
 ↓
Service Proxy
 ↓
Application

Every layer introduces:

Configuration
Latency
Failure Modes
Logs
Cost
Operational Complexity

Sometimes this complexity is justified.

Often it is not.

A strong architecture asks:

What unique responsibility does this layer provide?

If there is no clear answer, reconsider whether the layer is necessary.


Production Reverse Proxy Architecture

A mature deployment might look like:

                        Internet
                           │
                           ▼
                         DNS
                           │
                           ▼
                     CDN / Edge
                           │
                           ▼
                    Cloud Firewall
                           │
                           ▼
                    Load Balancer
                           │
              ┌────────────┴────────────┐
              ▼                         ▼
       Reverse Proxy A           Reverse Proxy B
              │                         │
              └────────────┬────────────┘
                           ▼
                    Application Tier
              ┌────────────┼────────────┐
              ▼            ▼            ▼
           App A         App B         App C
              │            │            │
              └────────────┼────────────┘
                           ▼
                      Data Layer

Caching may exist at several points:

Browser
 ↓
CDN
 ↓
Reverse Proxy
 ↓
Application Cache
 ↓
Database

Observability surrounds the entire path:

Logs
Metrics
Traces
Alerts

Security is layered:

Edge Security
+
Firewall
+
TLS
+
Proxy Policy
+
Application Authentication
+
Authorization
+
Network Segmentation
+
IAM

No individual component provides all of these protections.


Example Production Nginx Reverse Proxy

A simplified production-oriented configuration might resemble:

upstream app_backend {
    server 10.0.10.11:3000;
    server 10.0.10.12:3000;
}

server {
    listen 80;
    server_name example.com www.example.com;

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/ssl/example/fullchain.pem;
    ssl_certificate_key /etc/ssl/example/privkey.pem;

    client_max_body_size 10m;

    location / {
        proxy_pass http://app_backend;

        proxy_http_version 1.1;

        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;

        proxy_connect_timeout 5s;
        proxy_read_timeout 60s;
    }
}

This example demonstrates several important ideas:

HTTP → HTTPS Redirect
TLS Termination
Backend Pool
Forwarded Headers
Connection Timeout
Response Timeout

It should be adapted to the actual application rather than copied blindly into production.


Reverse Proxy Deployment Checklist

Before exposing a production reverse proxy, verify:

Networking

  • Is the public address correct?
  • Does DNS point to the correct endpoint?
  • Are backend routes correct?
  • Are only required ports open?
  • Can the proxy reach every backend?

TLS

  • Is the certificate valid?
  • Is the complete certificate chain configured?
  • Is automatic renewal working?
  • Is HTTP redirected appropriately?
  • Is backend TLS required?

Proxying

  • Is Host forwarded correctly?
  • Is the original client address preserved safely?
  • Is the original protocol preserved?
  • Are WebSockets configured if required?
  • Are timeout values appropriate?

Load Balancing

  • Are all backend servers reachable?
  • How are failures handled?
  • Is application state externalized?
  • Is session persistence actually required?

Security

  • Are backend servers private?
  • Are administrative interfaces protected?
  • Is rate limiting required?
  • Are request-size limits appropriate?
  • Are security headers defined correctly?
  • Are forwarded headers trusted only from known infrastructure?

Caching

  • Which routes are cacheable?
  • Are personalized responses excluded?
  • How are objects invalidated?
  • How does reverse-proxy caching interact with CDN caching?

Observability

  • Are access logs enabled?
  • Are error logs collected?
  • Is upstream latency monitored?
  • Are 5xx responses monitored?
  • Are request IDs propagated?

Availability

  • Is the reverse proxy a single point of failure?
  • Is failover tested?
  • Are backups/configuration copies available?
  • Is infrastructure reproducible?

Reverse Proxy Best Practices

A strong reverse-proxy architecture follows several principles.

Keep Backends Private

Expose the minimum infrastructure required to serve public traffic.

Preserve Request Context

Forward hostname, protocol, and client information correctly.

Do Not Trust Arbitrary Forwarded Headers

Only known proxy infrastructure should be allowed to establish trusted client metadata.

Centralize TLS Where It Simplifies Operations

But re-encrypt backend connections when the threat model requires it.

Monitor Upstream Latency

A reverse proxy often reveals backend performance problems before users can identify the actual cause.

Avoid Excessive Timeout Increases

A 504 error is often a symptom.

Find the slow component before simply extending timeout values.

Cache Only What Is Safe

Never allow personalized responses to enter shared caches accidentally.

Design for Failure

Assume:

Backend will fail.
Proxy will fail.
Network will fail.
DNS can fail.
Dependencies will fail.

Architecture should define what happens next.

Automate Configuration

Production proxy configuration should live in version control whenever possible.

This connects naturally with Infrastructure as Code Explained.


Frequently Asked Questions

What is a reverse proxy?

A reverse proxy is an intermediary server that accepts client requests on behalf of backend services and forwards those requests according to routing and infrastructure policies.

What is Nginx reverse proxy?

Nginx can accept HTTP or HTTPS traffic and forward it to application servers using directives such as proxy_pass. It can also perform routing, load balancing, caching, TLS termination, and other HTTP infrastructure functions.

What is the difference between a proxy and a reverse proxy?

A forward proxy represents clients when accessing external resources. A reverse proxy represents backend servers when accepting requests from clients.

Is Nginx a reverse proxy or web server?

It can be both. Nginx can serve static web content directly while also forwarding requests to backend applications.

Is a reverse proxy the same as a load balancer?

No. Reverse proxying describes an intermediary request-forwarding architecture. Load balancing describes distributing traffic among multiple destinations. A reverse proxy can also function as a load balancer.

Why put Nginx in front of Node.js?

Nginx can provide TLS termination, public-port handling, routing, caching, compression, logging, static-file delivery, and other infrastructure functionality while Node.js focuses on application logic.

Can a reverse proxy improve security?

Yes, as one layer of a broader security architecture. It can hide backend services, terminate TLS, limit requests, enforce selected HTTP policies, and reduce direct backend exposure. It does not replace firewalls, authentication, authorization, patching, or secure application design.

Can a reverse proxy cache content?

Yes. Products such as Nginx can cache eligible upstream responses, reducing application and database workload.

Can Nginx load balance traffic?

Yes. Nginx can distribute HTTP traffic across multiple upstream servers using supported load-balancing methods.

What causes 502 Bad Gateway?

Common causes include an unavailable backend, incorrect address or port, connection refusal, protocol mismatch, upstream TLS errors, application crashes, or invalid upstream responses.

What causes 504 Gateway Timeout?

A 504 commonly occurs when the proxy does not receive an upstream response within the configured time. The underlying cause may be a slow application, database, external API, or network path.

Should I use a CDN and reverse proxy together?

They often complement each other. A CDN can provide global caching and edge delivery while the reverse proxy controls origin routing and backend access.

Should every application use Nginx?

No. Managed cloud load balancers, application platforms, API gateways, and other proxies may already provide the required functionality. Infrastructure should solve defined requirements rather than adding layers automatically.


Final Thoughts

A reverse proxy appears simple:

Client
   │
   ▼
Proxy
   │
   ▼
Server

but in production it can become one of the most important control points in the application architecture.

It can transform a collection of directly exposed services:

Frontend :3000
API :4000
Admin :5000
Service :6000

into a controlled architecture:

                         Internet
                            │
                            ▼
                       CDN / Edge
                            │
                            ▼
                       HTTPS :443
                            │
                            ▼
                      Reverse Proxy
                            │
             ┌──────────────┼──────────────┐
             ▼              ▼              ▼
          Frontend         API           Admin
             │              │              │
             └──────────────┼──────────────┘
                            ▼
                       Data Layer

At this point the reverse proxy can become responsible for:

Routing
TLS
Load Balancing
Caching
Compression
WebSockets
Rate Limiting
Request Metadata
Security Policies
Logging
Backend Isolation

The most important architectural lesson, however, is not that every application needs every feature.

It is that every infrastructure layer should have a clearly defined responsibility.

The CDN should not exist merely because CDNs are popular.

The reverse proxy should not exist merely because Nginx is popular.

The load balancer should not exist merely because production diagrams contain one.

Each component should solve a measurable problem.

For a complete learning path, start with CDN Caching Explained to understand the cache layer that can sit ahead of the proxy.

Then use this reverse-proxy guide to understand origin routing.

Continue with Cloud Load Balancing Explained for backend traffic distribution and Servers and Infrastructure Explained for the systems underneath the application tier.

For distributed execution closer to users, continue with Edge Computing Explained.

For cloud network design, read Cloud Network Architecture: AWS vs Azure vs Google Cloud.

And for reproducible production infrastructure, continue with Infrastructure as Code Explained.

The resulting CorgiNetwork infrastructure learning path becomes:

DNS → Edge Computing → CDN Caching → Reverse Proxy → Load Balancing → Application Servers → Data Layer → Cloud Networking → Infrastructure as Code.

corginetwork

Recent Posts

AI Agents as Code: Git, Versioning & CI/CD Guide

AI Agents as Code: Managing AI Agent Configurations, Prompts and Tools with Git AI agents…

1 week ago

Data Center Power Distribution Architecture Guide

Data Center Power Distribution Architecture: UPS, PDU, Redundancy and Rack Power Explained Data center power…

1 week ago

DNSSEC Troubleshooting: How to Fix SERVFAIL, DS, DNSKEY and RRSIG Errors

DNSSEC Troubleshooting: Fix SERVFAIL & DNSKEY Errors DNSSEC Troubleshooting: How to Fix SERVFAIL, DS, DNSKEY…

2 weeks ago

Terraform State Management: Remote State, Locking & Backends

Terraform State Management Explained: Remote State, Locking, Backends and Best Practices Terraform makes infrastructure reproducible…

2 weeks ago

RTO vs RPO Explained: Disaster Recovery Objectives & Examples

RTO vs RPO Explained: Disaster Recovery Objectives, Examples and Planning A disaster recovery plan is…

2 weeks ago

Network Intrusion Detection: NIDS, Sensors & Traffic Analysis

Network Intrusion Detection Explained: NIDS, Sensors, Signatures and Traffic Analysis A firewall can decide whether…

2 weeks ago