Error guide
499 Client Closed Request
Nginx's own code for a client that hung up before the response was ready — a symptom of slowness, not a cause.
499 is not part of the HTTP specification. It is a code nginx writes into its own access log when a client disconnects before the response was sent — no response ever went out, so nothing received a 499. It exists purely so the log can record what happened.
That makes it a symptom with an unusually clear meaning. A client gave up waiting, which means the response was slow enough that something decided it was not coming: a user navigating away, a mobile app hitting its own timeout, a load balancer or a client library cutting the connection at a deadline shorter than the server's.
So the interesting number is never the 499s themselves — it is what the upstream was doing at the time. A rise in 499s is one of the earliest signals of a saturating backend, and it appears before the 502s and 504s that follow, because clients start giving up before the server does.
Common causes
- Upstream responses slow enough that clients time out first.
- A client-side or load-balancer timeout shorter than the server's own.
- Users abandoning a slow page or an app cancelling an in-flight request.
- A saturated connection pool or thread pool making requests queue before any work starts.
- Long-polling or streaming connections closing normally, which produce 499s that mean nothing.
How to diagnose it
- Correlate 499s against upstream response time — they almost always track the tail latency.
- Compare each layer's timeout: the shortest one decides who gives up first, and it is often the client.
- Separate long-polling and streaming endpoints, whose normal closes are indistinguishable in the log.
- Look for a matching rise in 502 or 504 shortly afterwards, which confirms the upstream is degrading.
- Check queue depth and pool saturation on the upstream at the times of the spikes.
Whose fault is it? The server's side
Formally the client closed the connection, but in practice a rise in 499s is a server-side latency problem. The client only gave up because the answer was late.
What monitoring sees
An external monitor will never receive a 499 — it is a log-only code — so it will not appear in check history at all. What a monitor can see is the cause: rising response time before failures start. A response-time threshold on a monitor catches this phase, which is the whole argument for alerting on latency rather than only on availability.
Related error guides
Terms used on this page
Questions
Is 499 a real HTTP status code?
No. It is nginx's own log-only code for a client that disconnected before the response was sent. Nothing ever receives a 499, which is why your monitoring will never report one.
How do I stop 499 errors?
Make the upstream faster, or reconcile the timeouts so the server is not still working on a request every client has already abandoned. Suppressing the log line changes nothing about what is happening.
One of the Uptimely HTTP and network error guides, written for the person who operates the server rather than the one refreshing the page. Something here read wrong to you? Email support@getuptimely.com.