Nginx Custom Status Codes: 444, 494, 495, 496, 499
Nginx defines several status codes not in the IANA registry. These codes appear in nginx access logs and error pages to describe connection-level events that the standard HTTP status code set cannot express precisely enough. Seeing a 499 in your nginx logs means a client closed the connection before nginx sent the response: useful for diagnosing timeout mismatches.1 A 444 means nginx deliberately dropped the connection without sending any response.2 A 494 means the request headers were too large for nginx's configured buffer.3 These codes are never sent to browsers as standard HTTP responses: browsers never see them as response status codes. Instead, they appear exclusively in nginx's own access and error logs. Understanding them prevents misdiagnosis of log anomalies that look alarming but have specific, diagnosable causes.
When nginx returns 499: client disconnect
Nginx records 499 Client Closed Request in its access log when the client closes the TCP connection before nginx finishes sending the response.1 This most commonly occurs when the client's request timeout is shorter than the time your application takes to generate the response, which is why 499 spikes often correlate with the release of a slower code path or a new external dependency that adds latency to previously fast endpoints.
A high 499 rate often indicates that upstream application processing is too slow: clients time out and disconnect before receiving the response. 499 entries are correlated with poor user experience even though the response was eventually generated: the user or API client saw a timeout, not a successful response. The wasted upstream work also consumes application resources that could have been used for requests that clients actually received, so a sustained 499 spike can trigger a secondary resource exhaustion problem on the application tier.
Comparing the 499 timestamp with the upstream response time logged by nginx shows how long the application took to respond and how much it exceeded the client's timeout. Load balancers that sit in front of nginx also generate client disconnects for idle connections that exceed their idle timeout, so a 499 spike that correlates with a load balancer idle timeout configuration change is a strong signal that the timeout value is too aggressive for your application's actual response time distribution.
Using 444 to drop connections
Nginx's 444 No Response code is used in nginx configuration to instruct nginx to close the TCP connection immediately without sending any response.2 This is a security measure for blocking malicious requests, crawlers, or known bad IP addresses without giving them any information about the server. Because no bytes are sent on the connection, a client that receives a 444 cannot determine whether the server exists, what software it runs, or what endpoints are available, which reduces the information an attacker can gather during reconnaissance.
Common use cases for 444
A common pattern is using 444 in a server block for unknown Host headers: if a request arrives with no matching virtual host, nginx closes the connection with 444. It is also appropriate for rate-limiting specific IPs at the nginx level without revealing that the server exists, for blocking scanners by their User-Agent, or for discarding requests that match known attack probe URI patterns.
444 should not be used for legitimate requests that simply fail validation: those should receive standard 4xx responses that the client can act on. Dropping the connection on a legitimate client request wastes their time and makes debugging harder, because the client receives a generic connection error instead of a specific status code that points to the actual problem.
Reading nginx access logs for non-standard codes
Nginx access logs include the status code as the third field in the standard combined log format: the log line "GET /path HTTP/1.1" 499 0 shows a 499 with zero bytes sent. Filtering for non-standard codes reveals specific operational patterns that would otherwise be buried in the noise of standard status codes, and setting up a dedicated log format that captures $status, $upstream_response_time, and $request_time makes it possible to correlate non-standard codes with upstream latency in a single query.
Diagnosing non-standard code clusters
A cluster of 494 codes indicates that some clients are sending oversized request headers, often due to large cookies or custom headers from a misconfigured application.3 A cluster of 495 or 496 codes indicates SSL client certificate validation failures, which only appear if you have configured mutual TLS.4 Grouping non-standard codes by User-Agent, source IP, and request path in your log analysis tool reveals whether the failures are concentrated in a single client, a single endpoint, or a single time window, which determines whether the fix belongs in nginx configuration, application code, or infrastructure capacity planning.
499 codes that correlate with specific endpoints point to slow upstream handlers for those routes. 499 codes that correlate with specific time windows point to upstream latency spikes caused by database load, garbage collection, or external API slowdowns. Setting up nginx log parsing with separate counters for non-standard codes makes these patterns visible automatically in your monitoring system.
Tuning nginx buffers to prevent 494 Request Header Too Large errors
Nginx's large_client_header_buffers directive controls how nginx allocates memory for incoming request headers. The default configuration allows four 8 KB buffers (32 KB total). When a single header field or the combined headers exceed this limit, nginx returns 494 Request Header Or Cookie Too Large and rejects the request. Large cookies are the most common cause: modern web applications accumulate cookies from analytics tools, A/B testing platforms, and session managers, sometimes pushing the total cookie header size past nginx's default limit.
Large cookies from analytics tools, A/B testing platforms, and session managers sometimes push the total header size past nginx's 32 KB default buffer, which triggers 494 request header too large and rejects the request. Diagnosing the header causing the 494 requires examining the raw request headers nginx received before rejecting the request. After identifying the oversized header, increase large_client_header_buffers 8 16k in your http or server block to accommodate larger headers. Enable the underscores_in_headers on directive if your application uses custom headers with underscores, since nginx silently drops these by default, which can confuse debugging when expected headers are missing.
Balancing buffer size against memory usage
Each nginx worker process allocates large_client_header_buffers memory per connection when reading request headers. Increasing the buffer size multiplies the memory usage by the number of concurrent connections your server handles. For a server handling 10,000 concurrent connections with large_client_header_buffers 8 32k, each worker may allocate up to 256 KB per connection for header buffers alone. Profile your actual header sizes from production logs before increasing buffer limits, and set the minimum size needed rather than using an arbitrarily large value.
When to use this
Use this guide when interpreting nginx access logs and error pages. Reference it to identify what a non-standard nginx code means and which layer of the stack it implicates.
Examples
499 spike appearing in nginx logs after a new upstream service was deployed
The new upstream service is responding too slowly for the client timeout. Check the upstream response time in the nginx log (the last field in the combined format). Identify which endpoints are slowest and optimise the upstream handler or increase the client timeout if the latency is acceptable.
494 errors appearing in logs from a specific user agent
The client is sending request headers that exceed nginx's large_client_header_buffers limit. Either increase the buffer size in nginx.conf or investigate why the client is sending unusually large headers (common with large cookies from multiple frameworks sharing a domain).
Blocking a known scanner IP range at the nginx level
Use "return 444;" in a geo or if block for the scanner IP range. Nginx closes the connection without sending any response, preventing the scanner from getting information about the server version or available endpoints.
- 1.
ServerFault, "Why does nginx always close the connection with return 444?," serverfault.com, accessed June 2026. https://serverfault.com/questions/1033849/why-does-nginx-always-close-the-connection-with-return-444
- 2.
Nginx, "ngx_http_rewrite_module: return directive," nginx.org, accessed June 2026. https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
- 3.
Nginx, "ngx_http_core_module: large_client_header_buffers," nginx.org, accessed June 2026. https://nginx.org/en/docs/http/ngx_http_core_module.html
- 4.
Stack Overflow, "Nginx default error page is still showing," stackoverflow.com, accessed June 2026. https://stackoverflow.com/questions/61155938/nginx-default-error-page-is-still-showing