Product

Product Features How to Compare Docs Screenshots Why

Start here

Getting started Download Guides Frequently asked questions

More

Security Support Roadmap About

Proxying and timeouts

16 answers

Getting a request to your application, and how long it waits.

Looking for something specific

The searchable index covers all 326 answers at once and filters as you type.

131 Turn on WebSockets

Open the site, Settings tab, WebSocket, and tick Enable WebSocket support. Save, then Apply config. That is the whole job.

Behind that one tick, nginx has to be told to speak HTTP/1.1 to the backend and to pass the upgrade headers through instead of swallowing them. Doing it by hand is three directives and a lookup table, and getting one of them wrong gives you a connection that opens and then dies with no useful error.

Chat, live dashboards, collaborative editors, terminal windows in a browser and anything using Socket.IO all need this.

websocketwswsssocket.ioupgraderealtime
132 My WebSocket drops after about a minute

The connection is idle and something closes it. Open the site, Settings tab, WebSocket, and raise WebSocket idle timeout. Ten minutes suits most applications, an hour suits a terminal or a dashboard somebody leaves open.

If it still drops, the application is probably not sending keepalive pings. Raising the timeout hides that for a while but does not fix it, because anything else in the path may have its own idea about idle connections.

websocket disconnectidle timeoutconnection closed60 seconds
133 Give a slow application more time to answer

Open the site, Settings tab, Proxy. Three boxes matter:

  • Connect timeout: how long to wait for the backend to pick up. Leave this short, a few seconds. A backend that will not accept a connection is not going to get better in a minute.
  • Read timeout: how long to wait for the answer once it has picked up. This is the one to raise for a report that takes two minutes to build.
  • Send timeout: how long to wait while sending the request. Only matters for large uploads.

Raise Read timeout for one slow path rather than the whole site if you can. Add the path, tick Settings for this path only, and set it there. A site wide two minute timeout means a genuinely broken backend holds connections for two minutes each.

504gateway timeoutslow backendread timeoutlong request
134 Stop slow visitors tying up my application

Leave Buffer responses on, which is the default. The load balancer takes the whole answer from your application as fast as the application can produce it, lets the application go, and then dribbles it out to the visitor at whatever speed the visitor has.

Without it, a worker on your application server is held open for the whole download. A few hundred people on bad connections is enough to fill up a small application server while the processor sits idle.

The buffer sizes are under Show advanced settings, but the defaults are sensible and almost nobody needs to change them.

bufferingslow clientsworker exhaustionproxy_buffering
135 Turn buffering off for streaming or server sent events

Buffering is exactly wrong for a response that is meant to arrive a piece at a time. With it on, a progress feed or an event stream sits in a buffer and arrives all at once at the end, which looks like the feature is broken.

  1. Add a path for the streaming endpoint, for example /events.
  2. Tick Settings for this path only.
  3. Turn Buffer responses off there.
  4. Raise Read timeout while you are in, because a stream is idle a lot.

Do it per path. Turning buffering off for the whole site gives back the slow client problem for every page on it.

server sent eventsSSEstreamingno bufferingprogress
136 Try the next backend when one fails

Open the site, Settings tab, Proxy, and tick Show advanced settings. The retry list appears: Connection error, Timed out, Backend sent garbage, and then the status codes 500, 502, 503, 504, 403 and 404.

Connection error, Timed out and 502 are safe and worth having on. 503 is usually worth it too, because it normally means a backend is restarting.

Leave 403 and 404 off. Those are real answers from a working application, and retrying them just asks three servers the same question and gets the same answer three times.

Maximum retries caps how many other backends get tried, and Total retry time caps how long the whole thing may take. Set both, or one slow failure can turn into a long one.

retrynext upstreamfailover502proxy_next_upstream
137 Stop retrying a request that changes something

A retry means the request is sent again. That is harmless for a page view and not harmless at all for a payment.

By default only GET and HEAD get retried, which is the safe choice. There is a box called Also retry POST and PATCH, and you should only tick it if you know the application handles being asked twice.

Never retry switches the whole thing off for that site or path. Worth it on a checkout, a webhook receiver, or anything that sends email.

idempotentdouble chargeretry POSTduplicatenon-idempotent
138 Control what name the backend thinks it is answering for

This lives on the pool, not the site, because it is a fact about the servers rather than about the address people type.

Open the pool, Load balancing tab, What is on the other end:

  • Servers running my app, answering to my site's name. The visitor's name is passed through. This is right for nearly everything you run yourself.
  • Another website, on its own name. The backend is told its own name instead. This is right when you are putting a load balancer in front of something that already thinks of itself as a website, like a hosted service or an appliance.

Choosing the second one also points the backend's redirects back at you, so a visitor is not quietly walked off onto the other site's own address halfway through.

Get this wrong and you get a certificate warning, a redirect loop, or an application that builds every link with the wrong hostname in it.

host headerproxy_set_header Hostwrong hostnamelinks wrong
139 Pass the visitor's real address to my application

Already done. Every proxied site sends the client address and the original scheme to the backend, because an application that logs the load balancer address for every request is no use to anybody.

What is left is the application end. Most frameworks ignore a forwarded address unless you tell them to trust the thing in front. Look for a trusted proxy setting and put the addresses of your load balancer nodes in it. Do not set it to trust everybody, or anybody can claim to be anybody.

The Cluster page lists the node addresses, which is what that setting wants.

X-Forwarded-Forreal ipclient addresstrusted proxyremote_addr
140 My application lives under a sub path on the backend

Two places can set this, and the pool is usually the better one.

If every site using those backends needs the prefix, it is a fact about the servers. Put it on the pool, Load balancing tab, Where the application sits on these backends. Set once, right for everything pointed at it.

If only this site needs it, because the same pool is also reached another way, use the site instead: Settings tab, Proxy, Backend lives under this path. That overrides whatever the pool says.

Either way the prefix is added on the way in and taken back off the redirects on the way out. The other half of this is usually Rewrite redirect locations and Rewrite cookie paths in the same section, because an application that thinks it lives under a prefix will put that prefix into both.

sub pathcontext pathbase pathapplication prefix
141 Stop a header my backend sends from reaching visitors

Open the site, Settings tab, tick Show advanced settings, then Proxy, Hide these response headers. One name per line.

Worth hiding: anything naming the framework or its version, internal request identifiers, debug headers somebody left on, and any header carrying an internal hostname. None of it helps a visitor and all of it helps somebody working out what to try next.

hide headerX-Powered-Byleakproxy_hide_headerversion disclosure
142 Keep connections to the backends open instead of making a new one every time

Open the pool, Load balancing tab, and set Keep-alive connections. Somewhere between 16 and 64 suits most setups. Requests per connection caps how many requests one connection handles before it is replaced.

Setting up a connection costs a round trip, and a TLS connection costs several. On a busy site that is a real slice of the response time, spent doing nothing useful.

Make sure the site is on HTTP/1.1 under Settings, Proxy. Keepalive does not work on HTTP/1.0 and the setting is quietly ignored.

keepaliveconnection reuseupstream keepalivelatency
143 I get a 502 and the logs mention headers being too big

Something is sending a header bigger than the space set aside for it. A long list of cookies and a large signed in token are the usual causes, and single sign on tokens are the usual suspect of all.

Open the site, Settings tab, tick Show advanced settings, then Proxy and raise Header buffer size. Under Limits and Timeouts, raise Large header buffers too, because that one covers what the visitor sends rather than what the backend sends back.

Doubling is usually enough. If doubling twice is not enough, something is putting far too much into a cookie and that is worth fixing at the source.

502header too largeupstream sent too big headercookie sizeJWT
144 Point a site at a backend whose address keeps changing

nginx normally looks a backend name up once at startup and holds on to it. That is fine for a fixed server and wrong for anything in a cloud that moves.

Open the site, Settings tab, tick Show advanced settings, go to Advanced and set a DNS resolver. Now the name is looked up again as its record expires rather than once, ever.

Use your own resolver or the one your cloud provides. Do not point it at a public resolver for an internal name, because it will not know the answer and you will get a wall of failures.

resolverdynamic dnschanging ipcloud backendstale ip
145 Speak https to a backend that has its own certificate name

Turn on Talk to these backends over https on the pool. Then, on the site, Settings tab, Proxy, with advanced settings shown, there are two more:

  • Send SNI to backend. Leave this on. Without it a backend hosting several names has no idea which certificate to present, and hands over the wrong one.
  • Verify backend certificate. Turn it on once the backend has a certificate that actually checks out. Leaving it off means the traffic is encrypted but you have not established who you are talking to, which is half a job.
backend tlsSNIverify certificatehttps backendupstream ssl
146 Show my own error pages when the backend breaks

Open the site, Settings tab, tick Show advanced settings, then Proxy, and tick Use my error pages for backend errors.

With it off, a 500 from your application is passed through exactly as the application wrote it, stack trace and all. With it on, the visitor gets the page you designed under Error Pages.

Careful with an API. An API client wants the JSON error the application sent, not a nicely designed HTML page it cannot parse. Turn this on for the site and off for the API path.

error pageintercept errors500 pagestack traceproxy_intercept_errors

Two fresh servers is all it takes

Ubuntu 22.04 or newer, root access, and about twenty minutes. The installer does the rest and it is safe to run twice.