When building and deploying modern web applications, you may hear terms like reverse proxy, Nginx, load balancer, web server, and API gateway.
These technologies often work behind the scenes, so understanding what they do can be confusing at first.
So, what is a reverse proxy, and why do websites and applications use one?
A reverse proxy is a server that sits between clients and one or more backend servers. Instead of clients communicating directly with the backend, their requests first go to the reverse proxy. The reverse proxy then forwards the requests to the appropriate backend server and returns the response to the client.
In this article, we’ll explain what a reverse proxy is, how a reverse proxy works, common use cases, Nginx configuration, reverse proxy vs forward proxy, reverse proxy vs load balancer, security benefits, and how reverse proxies are used in modern web applications.
What Is a Reverse Proxy?
A reverse proxy is a server that receives requests from clients and forwards those requests to backend servers.
From the client’s perspective, the reverse proxy looks like the actual application server.
A simplified architecture looks like this:
Client
|
| HTTP Request
↓
Reverse Proxy
|
| Forward Request
↓
Backend Server
|
| Response
↓
Reverse Proxy
|
↓
Client
For example, imagine your website is available at:
https://example.com
But your Node.js application is actually running internally on:
http://localhost:3000
Instead of exposing port 3000 directly to users, you can put Nginx in front of the application:
Internet
↓
example.com:443
↓
Nginx
↓
localhost:3000
↓
Node.js Application
The user only sees:
https://example.com
They don’t need to know that the application is running on port 3000.
How Does a Reverse Proxy Work?
The reverse proxy sits between the client and the backend.
Suppose you have:
Frontend:
https://example.com
Backend:
http://localhost:5000
When a user visits:
https://example.com/api/users
the request can follow this path:
Browser
↓
HTTPS Request
↓
Nginx Reverse Proxy
↓
http://localhost:5000/api/users
↓
Node.js API
↓
Response
↓
Nginx
↓
Browser
The reverse proxy receives the request, determines where it should go, forwards it, receives the response, and sends the response back to the client.
The client does not need to communicate directly with the backend server.
Why Do We Need a Reverse Proxy?
A reverse proxy can provide several useful capabilities between your users and application servers.
Common reasons to use a reverse proxy include:
- HTTPS termination
- Load balancing
- Security
- Request routing
- Caching
- Compression
- Rate limiting
- Hiding backend infrastructure
- Serving static files
- Connecting multiple applications
- Managing domains and subdomains
For example, a single server could host:
example.com
api.example.com
admin.example.com
The reverse proxy can route each domain to a different application.
Nginx
|
┌────────────┼────────────┐
↓ ↓ ↓
Frontend API Server Admin
:3000 :5000 :4000
Reverse Proxy Example
Let’s say you have three applications running on one server:
Next.js → localhost:3000
Node.js API → localhost:5000
Admin Panel → localhost:4000
You want users to access them through:
https://example.com
https://api.example.com
https://admin.example.com
Nginx can act as the reverse proxy.
Internet
|
Nginx
___________|____________
| | |
↓ ↓ ↓
localhost:3000 localhost:5000 localhost:4000
Next.js Node.js Admin
This allows multiple applications to run behind a single public-facing server.
What Is Nginx?
NGINX is one of the most commonly used technologies for reverse proxying.
Nginx can act as:
- Web server
- Reverse proxy
- Load balancer
- HTTP cache
- SSL/TLS termination point
- Static file server
For example, a simple Nginx reverse proxy configuration might look like:
server {
listen 80;
server_name 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;
}
}
Here:
example.com
↓
Nginx
↓
localhost:3000
The proxy_pass directive tells Nginx where to send the request.
Reverse Proxy With Node.js
A common Node.js deployment architecture looks like:
User
↓
HTTPS
↓
Nginx
↓
Node.js
↓
MongoDB
Your Node.js application might listen on:
localhost:5000
Nginx can expose it publicly through:
https://api.example.com
A configuration could look like:
server {
listen 443 ssl;
server_name api.example.com;
location / {
proxy_pass http://localhost:5000;
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;
}
}
The Node.js server can remain bound to the local server interface rather than being directly exposed to the public internet.
Reverse Proxy and HTTPS
One of the most common uses of a reverse proxy is handling HTTPS.
Instead of configuring TLS certificates independently inside every backend application, the reverse proxy can terminate HTTPS connections.
For example:
Client
|
| HTTPS
↓
Nginx
|
| HTTP / internal network
↓
Node.js
Nginx handles the TLS connection from the client.
This is commonly called TLS termination or SSL termination.
In some architectures, the connection between Nginx and the backend can also use HTTPS if required.
Reverse Proxy for Multiple Applications
Suppose you have:
Next.js application → port 3000
Node.js API → port 5000
Laravel application → port 8000
You could route traffic based on domains:
example.com
↓
localhost:3000
api.example.com
↓
localhost:5000
admin.example.com
↓
localhost:8000
Nginx acts as the central entry point.
This is especially useful on VPS servers where several applications are hosted on the same machine.
Reverse Proxy for Path-Based Routing
You don’t always need different domains.
You can also route traffic based on URL paths.
For example:
example.com/
↓
Next.js
example.com/api/
↓
Node.js
example.com/admin/
↓
Admin application
An Nginx configuration might look like:
server {
listen 80;
server_name example.com;
location /api/ {
proxy_pass http://localhost:5000;
}
location / {
proxy_pass http://localhost:3000;
}
}
Now the reverse proxy decides where the request should go based on the URL.
Reverse Proxy vs Forward Proxy
These two terms are easy to confuse.
The main difference is who the proxy represents.
Forward Proxy
A forward proxy represents the client.
Client
↓
Forward Proxy
↓
Internet
The destination server sees the proxy rather than directly seeing the client.
Forward proxies are commonly used for:
- Corporate networks
- Internet access control
- Privacy
- Content filtering
- Network monitoring
Reverse Proxy
A reverse proxy represents the server.
Client
↓
Reverse Proxy
↓
Backend Server
The client communicates with the reverse proxy, which forwards the request to the backend.
Simple Difference
Remember:
Forward Proxy → Protects/represents clients
Reverse Proxy → Protects/represents servers
Reverse Proxy vs Load Balancer
A reverse proxy and a load balancer are related, but they aren’t exactly the same concept.
A reverse proxy forwards requests from clients to backend servers.
A load balancer distributes requests across multiple backend servers.
For example:
Reverse Proxy
|
┌───────────┼───────────┐
↓ ↓ ↓
Server 1 Server 2 Server 3
In this architecture, the reverse proxy can also perform load balancing.
For example, Nginx can distribute requests across multiple Node.js instances:
upstream backend {
server 127.0.0.1:5001;
server 127.0.0.1:5002;
server 127.0.0.1:5003;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
Now requests can be distributed across the backend instances.
Reverse Proxy Load Balancing
Imagine your application receives a large number of requests.
Instead of running one Node.js process:
Node.js
↓
100% traffic
you can run multiple instances:
Nginx
|
┌───────┼───────┐
↓ ↓ ↓
Node.js Node.js Node.js
:5001 :5002 :5003
The reverse proxy distributes requests between these instances.
This can improve scalability and availability.
Common load-balancing strategies include:
- Round robin
- Least connections
- IP hash
- Weighted routing
Reverse Proxy and Caching
A reverse proxy can also cache responses.
For example:
Client
↓
Reverse Proxy
↓
Cache?
↙ ↘
Yes No
↓ ↓
Response Backend
If a requested resource is already cached, the reverse proxy may return it without contacting the backend.
This can reduce:
- Backend requests
- Server workload
- Database queries
- Response latency
Caching strategies should be carefully designed because stale data can cause incorrect responses.
Reverse Proxy and Security
A reverse proxy can add an additional security layer between the public internet and backend servers.
For example:
Internet
↓
Reverse Proxy
↓
Private Backend
The backend servers don’t necessarily need to be directly exposed to the public internet.
A reverse proxy can also be combined with:
- Web application firewalls
- Rate limiting
- IP filtering
- Authentication
- Request validation
- DDoS protection
- TLS termination
However, a reverse proxy by itself is not a complete security solution.
Reverse Proxy and Rate Limiting
A reverse proxy can limit how many requests a client can make within a particular period.
For example:
Client
↓
100 requests/minute
↓
Reverse Proxy
↓
Rate Limit
↓
Backend
If the client exceeds the configured limit, the proxy can reject additional requests.
This can help protect APIs from excessive traffic and some types of abuse.
Reverse Proxy and Static Files
A reverse proxy such as Nginx can also serve static files directly.
For example:
/images/logo.png
/css/style.css
/js/app.js
Instead of sending these requests to Node.js, Nginx can serve them directly from the filesystem.
This can reduce the workload on the application server.
A typical architecture might be:
Nginx
/ \
/ \
Static Files Node.js
Reverse Proxy for Next.js
Next.js applications can also be deployed behind a reverse proxy.
For example:
User
↓
Nginx
↓
Next.js
↓
Application
Suppose Next.js is running on:
localhost:3000
Nginx can expose it as:
https://example.com
A simple configuration could be:
server {
listen 80;
server_name 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;
}
}
This architecture is common when deploying applications on VPS infrastructure.
Reverse Proxy vs API Gateway
An API gateway and reverse proxy can perform overlapping functions, but they are usually used at different levels of complexity.
A reverse proxy primarily handles traffic between clients and backend services.
An API gateway can provide additional API-specific capabilities such as:
- Authentication
- Authorization
- Rate limiting
- API versioning
- Request transformation
- Service discovery
- Analytics
- Routing
For a simple application:
Client
↓
Nginx
↓
API
may be enough.
For a large microservices architecture:
Client
↓
API Gateway
↓
Service A
Service B
Service C
Service D
an API gateway may be more appropriate.
Reverse Proxy in Microservices
Reverse proxies are commonly used in microservice architectures.
Imagine an application has:
User Service
Order Service
Payment Service
Notification Service
A reverse proxy or gateway can route requests:
Gateway
|
┌───────────┼───────────┐
↓ ↓ ↓
Users Orders Payments
Service Service Service
The client doesn’t need to know the internal location of each service.
This provides a layer of abstraction between clients and backend infrastructure.
Reverse Proxy Request Headers
When a reverse proxy forwards requests, the backend may need information about the original client request.
Common headers include:
Host
X-Real-IP
X-Forwarded-For
X-Forwarded-Proto
For example:
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;
These headers can help the backend understand information about the original request.
Applications should treat forwarded headers carefully and configure trusted proxies correctly rather than blindly trusting client-supplied values.
Common Reverse Proxy Problems
Although reverse proxies are powerful, they can introduce configuration issues.
1. 502 Bad Gateway
A 502 Bad Gateway error often occurs when the reverse proxy cannot successfully communicate with the backend.
For example:
Nginx
↓
localhost:3000
↓
Application not running
Nginx may return a 502 response.
2. Incorrect Port
If your application is running on:
localhost:8080
but Nginx forwards requests to:
localhost:3000
the proxy will fail.
3. WebSocket Issues
Applications using WebSockets may require additional proxy configuration.
For example:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
4. Incorrect Host Configuration
Incorrect Host or forwarded headers can cause problems with applications that rely on the original domain.
5. Timeout Problems
Long-running API requests may require appropriate proxy timeout configuration.
Reverse Proxy Best Practices
If you’re using a reverse proxy in production, consider these practices.
Use HTTPS
Protect client-to-proxy communication with TLS.
Keep Backend Services Private
Where possible, don’t expose internal application ports directly to the internet.
Configure Health Checks
When using multiple backend instances, monitor whether they are available.
Use Rate Limiting
Protect public APIs from excessive traffic.
Configure Timeouts
Prevent connections from remaining open indefinitely.
Monitor Logs
Reverse proxy access and error logs can be extremely useful when troubleshooting deployment problems.
Forward Required Headers
Make sure your application receives the information it actually needs.
Don’t Trust Forwarded Headers Blindly
Only trust proxy-generated headers from known, trusted proxy infrastructure.
Reverse Proxy Architecture Example
A modern production web application might look like this:
Internet
|
↓
Reverse Proxy
/ \
/ \
HTTPS Rate Limit
| |
└─────┬──────┘
↓
Application Server
/ \
↓ ↓
Node.js Next.js
| |
└──────┬───────┘
↓
Database
For larger systems, the reverse proxy may sit in front of multiple services:
Users
|
↓
Load Balancer
|
↓
Reverse Proxy
|
┌──────────────┼──────────────┐
↓ ↓ ↓
API Server Web Server Static Files
|
↓
Database
This architecture separates public traffic from internal application services.
Frequently Asked Questions
What is a reverse proxy in simple terms?
A reverse proxy is a server that receives requests from users and forwards them to the appropriate backend server.
Is Nginx a reverse proxy?
Yes. Nginx can function as a reverse proxy, web server, load balancer, and more.
Is a reverse proxy a load balancer?
A reverse proxy can perform load balancing, but the terms are not identical. A load balancer specifically distributes traffic across multiple servers.
Is a reverse proxy secure?
A reverse proxy can improve security by hiding backend infrastructure and providing features such as TLS termination and rate limiting, but it does not automatically make an application secure.
Why use Nginx with Node.js?
Nginx can handle HTTPS, routing, static files, buffering, and reverse proxying while Node.js focuses on application logic.
Can Nginx proxy a Next.js application?
Yes. Nginx can forward requests to a Next.js server running on an internal port.
Can one reverse proxy handle multiple applications?
Yes. It can route requests based on domains, subdomains, URL paths, or other rules.
What is the difference between a reverse proxy and a proxy?
A forward proxy represents clients, while a reverse proxy represents servers.
Conclusion
A reverse proxy is an important component in modern web application infrastructure.
Instead of allowing users to communicate directly with backend servers, the reverse proxy sits in front of them:
Client
↓
Reverse Proxy
↓
Backend
This simple architecture enables many useful capabilities, including:
- HTTPS termination
- Load balancing
- Request routing
- Caching
- Rate limiting
- Static file serving
- Security controls
- Multiple application deployments
Tools such as Nginx are commonly used to implement reverse proxy architectures for Node.js, Next.js, Laravel, Python, and other web applications.
For a small application, a reverse proxy may simply forward requests from a public domain to an application running on an internal port.
For larger systems, it can become an important part of a scalable architecture that includes multiple application servers, load balancing, caching, security layers, and microservices.
The easiest way to remember what a reverse proxy is is:
A reverse proxy is the gateway between users and your backend servers.
Once you understand this concept, technologies such as Nginx, load balancers, API gateways, HTTPS termination, and microservice routing become much easier to understand.




