What is a reverse proxy?

A reverse proxy is a server that sits in front of your application, receives client requests and forwards them to the app. It can handle HTTPS, caching and load balancing without changing your code.

Updated 5 min read

Learning objectives

After reading this article you will be able to:

  • Understand what a reverse proxy does and how it differs from a forward proxy
  • Know what it is for: HTTPS, caching, load balancing and protection
  • Set up a simple nginx reverse proxy, including WebSocket
On this page

When you open a website, you almost never talk directly to the program that builds the page. Somewhere in between, a server receives your request and hands it to the app. That intermediary is the reverse proxy, and it sits in front of most sites and APIs you use.

Understanding it answers common questions: where HTTPS is configured, why your app sees the wrong IP, how to run two apps on the same public ports, and why a WebSocket drops after a minute.

Browserexample.comMobile appapi.example.comHTTPSReverse proxyends TLS, reads the Hostprivate networkHTTPWebsiteHost: example.comAPIHost: api.example.com
Clients only talk to the proxy: it takes the HTTPS and, by Host, hands each request to an internal app over HTTP.

What is a reverse proxy?#

A reverse proxy is a server that receives requests on behalf of other servers and forwards them. The client talks only to it. The server behind it, called the upstream or backend, never receives direct connections from the internet.

The name comes from the contrast with the ordinary proxy. A forward proxy acts on behalf of the client: a company uses one to filter what employees can visit, and the destination site sees the proxy's IP. A reverse proxy acts on behalf of the server: the client sees the proxy's address and has no idea how many apps are behind it.

Well-known examples: nginx, Caddy, HAProxy, Traefik and Envoy. CDN services also work as a global reverse proxy.

How does a reverse proxy work?#

A request goes through five steps:

  1. The browser resolves the domain through DNS and connects to the proxy's IP.
  2. The proxy accepts the connection and, for HTTPS, performs the TLS handshake.
  3. It reads the request (method, path, Host header) and decides which upstream gets it.
  4. It opens a connection to the upstream, usually on the same machine or private network, and forwards the request.
  5. It receives the response and returns it to the client.

Because the proxy reads the request, it can change it on the way: add headers, rewrite paths, cache the response or refuse the connection.

What is a reverse proxy used for?#

  • HTTPS in one place. The proxy terminates TLS and speaks plain HTTP to the app on the internal network. Your code never handles certificates. See what SSL/TLS is.
  • Many apps on one IP. Using the Host header, the proxy sends api.example.com to one app and example.com to another, both on ports 80 and 443.
  • Load balancing. The proxy spreads requests across several copies of the app. That is the topic of what a load balancer is.
  • Caching. Responses that do not change are served from the proxy's memory or disk without waking the app. At global scale, this is a CDN.
  • Protection. The app is not exposed. The proxy can rate limit by IP, block attack patterns and hide infrastructure details.
  • Compression and HTTP/2. The proxy compresses responses and speaks modern protocols to the client even if the app only understands HTTP/1.1.

How do you set up a reverse proxy with nginx?#

Assume a Node.js app listening on 127.0.0.1:3000. The file below sends everything that reaches the domain to it:

nginx
server {
    listen 80;
    server_name example.com;

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

What each line does:

  • proxy_pass sets the upstream. It can be http://, https:// or a Unix socket.
  • By default, nginx sends the upstream Host: $proxy_host, which is the upstream's own address. proxy_set_header Host $host forwards the domain the client asked for, which many frameworks expect.
  • X-Forwarded-For carries the list of IPs the request passed through. $proxy_add_x_forwarded_for appends the IP of whoever connected to the proxy to the value the client already sent.
  • X-Forwarded-Proto tells the app whether the client used http or https, which it needs to build correct links and redirects.

Check the syntax with nginx -t and reload with nginx -s reload.

What if the app uses WebSocket?#

Upgrade and Connection are hop-by-hop headers: nginx does not pass them on by itself. Without them the WebSocket handshake fails. Add a dedicated location:

nginx
location /ws/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

By default, nginx closes the connection if the upstream sends no data for 60 seconds. For idle connections, raise proxy_read_timeout as above or have the app send ping frames periodically.

How does the app learn the user's real IP?#

Behind a proxy, the connection reaching the app comes from the proxy, so the source IP is the proxy's. The client IP travels in X-Forwarded-For, formatted as client, proxy1, proxy2. MDN describes it as a de facto standard; the standardized version is Forwarded, which is much less used.

There is a risk: any client can send a fake X-Forwarded-For. For rate limiting or access control, use only the IPs added by proxies you trust, counting from the right of the list. If the app can be reached directly from the internet, no part of the header can be trusted. Frameworks have an option for this, such as trust proxy in Express.

When don't you need a reverse proxy?#

  • Bots that only make outbound connections (Discord, Telegram via long polling) receive no requests.
  • A single simple app on a platform that already serves HTTPS in front of it does not need you to install nginx yourself.
  • Non-HTTP protocols, such as a direct database connection, need a TCP (layer 4) proxy or no proxy at all.

Each extra layer is one more piece to configure and monitor, and one more thing that can fail. Add one when you have a concrete reason.

How to do this on Square Cloud#

On Square Cloud you do not install or configure a reverse proxy for the common case. Every web application gets a *.squareweb.app subdomain with HTTPS on any plan, and TLS is automatic. The edge takes the HTTPS connection, redirects HTTP to HTTPS and forwards the request to your app, which only has to listen on 0.0.0.0 on the port in the PORT variable.

The network includes an Anycast CDN with more than 200 points of presence, HTTP/3, WebSockets, WAF and L3/L4/L7 DDoS mitigation. The proxy does not cut long connections: WebSocket and SSE pass through without buffering.

Starting with the Standard plan, you point your own domain by creating the DNS records shown in the dashboard at your registrar. The domain stays registered in your name, and the dashboard shows validation status in real time.

To spread traffic across copies of your app, load balancing serves one custom domain from several applications, with round-robin, passive failover and no sticky sessions: up to 2 applications per domain on Standard, up to 5 on Pro and up to 10 on Enterprise.

See the network layer details in Network and CDN.

Network

Custom domains, automatic TLS and a global CDN for your app

Learn more

FAQs

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

A forward proxy sits on the client side and hides who is asking. A reverse proxy sits on the server side and hides who is answering. In both cases the proxy is an intermediary.

Is a reverse proxy the same as a load balancer?

No, but they overlap. Every HTTP load balancer acts as a reverse proxy, but a reverse proxy can sit in front of a single server, and then nothing is being balanced.

Do I need a reverse proxy for a bot?

Almost never. A bot that only opens outbound connections to the platform API does not receive HTTP requests. A reverse proxy makes sense for sites and APIs that receive traffic.

Why does my app show the proxy IP instead of the user IP?

Because the connection reaching your app comes from the proxy. The original IP travels in a header such as X-Forwarded-For, and your app must be configured to read it, trusting only your own proxy.

Next articleWhat is a subdomain?A subdomain is a prefix before your main domain, like api.example.com. Learn how it works in DNS, how to create one, and when to pick it over a subfolder.

More in Networking and domains

See all 27 articles