<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>NGINX Operations Guides on Netdata</title><link>https://www.netdata.cloud/guides/nginx/</link><description>Recent content in NGINX Operations Guides on Netdata</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://www.netdata.cloud/guides/nginx/index.xml" rel="self" type="application/rss+xml"/><item><title>How NGINX actually works in production: a mental model for operators</title><link>https://www.netdata.cloud/guides/nginx/how-nginx-works-in-production/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/how-nginx-works-in-production/</guid><description>&lt;h1 id="how-nginx-actually-works-in-production-a-mental-model-for-operators">How NGINX actually works in production: a mental model for operators&lt;/h1>
&lt;p>NGINX is not a multi-threaded server that spawns a thread per connection. It is an event-driven, non-blocking, single-threaded-per-worker process architecture. If you are debugging a production incident where connections are timing out, memory is climbing, or CPU is pinned, this architecture is the lens through which every symptom must be interpreted.&lt;/p>
&lt;p>Most production issues involving NGINX are not NGINX bugs. They are resource accounting problems: file descriptors, connection slots, buffer boundaries, or event loop latency. An operator who understands the internal mechanics can read the signals correctly instead of chasing phantom upstream problems or adding hardware that hits the same limit.&lt;/p></description></item><item><title>NGINX $request_time vs $upstream_response_time: isolating where latency lives</title><link>https://www.netdata.cloud/guides/nginx/nginx-request-time-vs-upstream-response-time/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-request-time-vs-upstream-response-time/</guid><description>&lt;h1 id="nginx-request_time-vs-upstream_response_time-isolating-where-latency-lives">NGINX $request_time vs $upstream_response_time: isolating where latency lives&lt;/h1>
&lt;p>P95 $request_time doubles. The default assumption is upstream degradation, so you scale the backend, tune the database, and add instances. The latency barely moves. The bottleneck was a slow mobile client, proxy temp-file disk I/O, or a large request body on a lossy network. This is the most common nginx misdiagnosis.&lt;/p>
&lt;p>$request_time measures the full cycle from the first byte read from the client to the last byte sent to the client. It includes reading the request, waiting for the upstream, and writing the response. $upstream_response_time measures only the backend portion, from establishing the upstream connection to receiving the last byte of the response body. The gap between them is where client-side, network, and nginx-internal delays live. To avoid chasing phantom backend problems, log both variables and compare them.&lt;/p></description></item><item><title>nginx 413 Request Entity Too Large: client_max_body_size explained</title><link>https://www.netdata.cloud/guides/nginx/nginx-413-request-entity-too-large/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-413-request-entity-too-large/</guid><description>&lt;h1 id="nginx-413-request-entity-too-large-client_max_body_size-explained">nginx 413 Request Entity Too Large: client_max_body_size explained&lt;/h1>
&lt;p>A &lt;code>413 Request Entity Too Large&lt;/code> after adding &lt;code>client_max_body_size 50m&lt;/code> to &lt;code>nginx.conf&lt;/code> usually means a more specific context still overrides it, or the upstream application rejects the body after nginx accepts it. The directive applies to &lt;code>http&lt;/code>, &lt;code>server&lt;/code>, and &lt;code>location&lt;/code> blocks. Raising it at the edge only moves the failure deeper if the rest of the stack is not adjusted. This guide covers how the directive inherits, when nginx fires the 413, how &lt;code>proxy_request_buffering&lt;/code> changes the failure mode, and why you must verify every hop including the upstream application.&lt;/p></description></item><item><title>nginx 499 status code: why clients close connections before the response</title><link>https://www.netdata.cloud/guides/nginx/nginx-499-client-closed-connection/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-499-client-closed-connection/</guid><description>&lt;h1 id="nginx-499-status-code-why-clients-close-connections-before-the-response">nginx 499 status code: why clients close connections before the response&lt;/h1>
&lt;p>Status 499 in nginx access logs means the client closed the TCP connection before nginx finished responding. It is an nginx-specific code that never reaches the client, so it is easy to dismiss. In practice, a 499 surge is an early warning: users or intermediaries abandon requests before upstreams officially time out and before 5xx errors spike. Ignore 499s and you usually see 502s or 504s minutes later.&lt;/p></description></item><item><title>nginx 500 Internal Server Error: how to diagnose it</title><link>https://www.netdata.cloud/guides/nginx/nginx-500-internal-server-error/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-500-internal-server-error/</guid><description>&lt;h1 id="nginx-500-internal-server-error-how-to-diagnose-it">nginx 500 Internal Server Error: how to diagnose it&lt;/h1>
&lt;p>A 500 from nginx tells you something failed in the request path, but not whether the failure originated in your application, FastCGI/uWSGI backend, or nginx itself. When 500s spike during an incident, first determine which side of the nginx boundary is breaking.&lt;/p>
&lt;p>Unlike 502 Bad Gateway or 504 Gateway Time-out, which point upstream, a 500 can be an application bug passed through by nginx, a configuration error, a permission failure, or resource exhaustion inside an nginx worker.&lt;/p></description></item><item><title>NGINX 502 Bad Gateway: Causes And How To Fix It</title><link>https://www.netdata.cloud/guides/nginx/nginx-502-bad-gateway/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-502-bad-gateway/</guid><description>&lt;p>A 502 Bad Gateway means the upstream server returned an invalid response, refused the connection, or terminated before completing the response. Unlike 504, which signals upstream slowness, 502 means the upstream never produced a valid response or nginx could not reach it.&lt;/p>
&lt;p>Start with the error log. A single line like &lt;code>connect() failed (111: Connection refused)&lt;/code> tells you the upstream is not listening. A line like &lt;code>upstream prematurely closed connection&lt;/code> tells you the backend died mid-request. Match the exact message to the root cause.&lt;/p></description></item><item><title>nginx 503 Service Temporarily Unavailable: causes and fixes</title><link>https://www.netdata.cloud/guides/nginx/nginx-503-service-unavailable/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-503-service-unavailable/</guid><description>&lt;h1 id="nginx-503-service-temporarily-unavailable-causes-and-fixes">nginx 503 service temporarily unavailable: causes and fixes&lt;/h1>
&lt;p>A &lt;code>503 Service Temporarily Unavailable&lt;/code> from nginx does not always mean the upstream application is broken. A healthy nginx process returns 503 by design when rate limits reject traffic, or when every backend in an upstream block is unavailable. The same status code covers three different failure paths: intentional throttling, upstream exhaustion, or resource saturation on the nginx host. The fix depends on which path the request took.&lt;/p></description></item><item><title>NGINX 504 Gateway Time-Out: Causes &amp; Fixes</title><link>https://www.netdata.cloud/guides/nginx/nginx-504-gateway-timeout/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-504-gateway-timeout/</guid><description>&lt;p>A 504 Gateway Time-out means nginx reached the upstream but the upstream did not finish its response before &lt;code>proxy_read_timeout&lt;/code> expired. The default is 60 seconds. Unlike a 502 Bad Gateway, which means nginx never established a valid upstream connection, a 504 means the connection succeeded but the response did not complete in time.&lt;/p>
&lt;p>This guide covers isolating slow upstreams via access log variables, tuning timeouts and retries, and distinguishing 504 from 502.&lt;/p></description></item><item><title>NGINX access log performance: buffering, sampling, and the event loop</title><link>https://www.netdata.cloud/guides/nginx/nginx-access-log-performance/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-access-log-performance/</guid><description>&lt;h1 id="nginx-access-log-performance-buffering-sampling-and-the-event-loop">NGINX access log performance: buffering, sampling, and the event loop&lt;/h1>
&lt;p>Every NGINX worker is a single-threaded event loop. By default, finishing a request triggers an immediate, synchronous write of the access log line. Under normal load the cost is negligible. Under incident conditions, when error rates and log volume spike, that synchronous write becomes a compounding failure: disk I/O stalls the event loop, responses slow down, clients time out, and the resulting errors and abandonments generate even more log lines.&lt;/p></description></item><item><title>NGINX active connections climbing: reading, writing, waiting explained</title><link>https://www.netdata.cloud/guides/nginx/nginx-active-connections-high/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-active-connections-high/</guid><description>&lt;h1 id="nginx-active-connections-climbing-reading-writing-waiting-explained">NGINX active connections climbing: reading, writing, waiting explained&lt;/h1>
&lt;p>When operators see Active connections climbing in &lt;code>stub_status&lt;/code>, the first instinct is often to add capacity. That instinct is usually wrong. The &lt;code>stub_status&lt;/code> module exposes exactly seven metrics, and the most useful of them is the breakdown of active connections into Reading, Writing, and Waiting. The absolute number of active connections is almost meaningless without the ratio between these three states. A server with 10,000 active connections where 9,000 are Waiting is healthy. A server with 500 active connections where 400 are Reading may be under a slowloris-style attack.&lt;/p></description></item><item><title>NGINX backend cascade failure: when slow upstreams take down everything</title><link>https://www.netdata.cloud/guides/nginx/nginx-backend-cascade-failure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-backend-cascade-failure/</guid><description>&lt;h1 id="nginx-backend-cascade-failure-when-slow-upstreams-take-down-everything">NGINX backend cascade failure: when slow upstreams take down everything&lt;/h1>
&lt;p>Users report timeouts. 502 Bad Gateway and 504 Gateway Time-out responses are climbing, and nginx error logs show upstream timeouts. On the nginx host, CPU and memory are normal, and the master process is alive. The proxy is healthy but out of connections.&lt;/p>
&lt;p>This is a backend cascade failure. One slow upstream causes nginx workers to hold connections open while waiting for responses, consuming finite &lt;code>worker_connections&lt;/code> slots. As slots fill, new requests cannot be forwarded. Traffic concentrates on the remaining healthy backends, which overload and slow down. Eventually every backend times out or fails health checks, and nginx returns 502/504 to all clients while the proxy process remains up.&lt;/p></description></item><item><title>nginx connect() failed (111: Connection refused) while connecting to upstream</title><link>https://www.netdata.cloud/guides/nginx/nginx-connect-failed-connection-refused-upstream/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-connect-failed-connection-refused-upstream/</guid><description>&lt;h1 id="nginx-connect-failed-111-connection-refused-while-connecting-to-upstream">nginx connect() failed (111: Connection refused) while connecting to upstream&lt;/h1>
&lt;p>HTTP 502 Bad Gateway and the error &lt;code>connect() failed (111: Connection refused) while connecting to upstream&lt;/code> mean nginx reached the upstream IP, but the target port actively refused the TCP connection. The backend is either not running, not listening on the interface nginx expects, or a firewall is blocking the port.&lt;/p>
&lt;p>This is distinct from &lt;code>upstream timed out (110: Connection timed out)&lt;/code>. A timeout means the TCP SYN never received a response, usually because a firewall silently dropped the packet or the host is unreachable. Errno 111 means the network path is open but no process is accepting connections. The error log includes the upstream address, such as &lt;code>upstream: &amp;quot;fastcgi://127.0.0.1:9000&amp;quot;&lt;/code>. Read that line first to isolate the exact backend.&lt;/p></description></item><item><title>NGINX connection exhaustion: detection, diagnosis, and prevention</title><link>https://www.netdata.cloud/guides/nginx/nginx-connection-exhaustion/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-connection-exhaustion/</guid><description>&lt;h1 id="nginx-connection-exhaustion-detection-diagnosis-and-prevention">NGINX connection exhaustion: detection, diagnosis, and prevention&lt;/h1>
&lt;p>Users see connection timeouts while load balancer health checks and the NGINX &lt;code>stub_status&lt;/code> endpoint still return HTTP 200. New connections are silently dropped. Connection exhaustion is a cliff-edge failure: once the limit is hit, there is no graceful degradation. Connections are refused at the kernel level, or accepted into the TCP backlog but discarded by NGINX because no worker has a free connection slot.&lt;/p></description></item><item><title>NGINX DNS resolution failures on dynamic upstreams: 502s and resolver_timeout</title><link>https://www.netdata.cloud/guides/nginx/nginx-dns-resolution-failures-upstream/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-dns-resolution-failures-upstream/</guid><description>&lt;h1 id="nginx-dns-resolution-failures-on-dynamic-upstreams-502s-and-resolver_timeout">NGINX DNS resolution failures on dynamic upstreams: 502s and resolver_timeout&lt;/h1>
&lt;h2 id="what-this-means">What this means&lt;/h2>
&lt;p>Intermittent 502 Bad Gateway responses that only hit locations using a variable in &lt;code>proxy_pass&lt;/code>, such as &lt;code>proxy_pass http://$backend;&lt;/code>, point to dynamic DNS resolution failure. Static upstream locations are unaffected. &lt;code>dig&lt;/code> from the host may succeed instantly while nginx logs show 502s with latency spikes clustering at exactly 30 seconds, the default &lt;code>resolver_timeout&lt;/code>.&lt;/p>
&lt;p>nginx resolves upstream hostnames through two paths.&lt;/p></description></item><item><title>NGINX dropped connections: the accepts vs handled gap</title><link>https://www.netdata.cloud/guides/nginx/nginx-dropped-connections/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-dropped-connections/</guid><description>&lt;h1 id="nginx-dropped-connections-the-accepts-vs-handled-gap">NGINX dropped connections: the accepts vs handled gap&lt;/h1>
&lt;p>Users report intermittent connection timeouts. Your HTTP 5xx rate is flat. The error log is quiet. Something is dropping traffic before it ever becomes a request.&lt;/p>
&lt;p>On every NGINX instance, the &lt;code>stub_status&lt;/code> page exposes two cumulative counters: &lt;code>accepts&lt;/code> and &lt;code>handled&lt;/code>. When &lt;code>accepts&lt;/code> grows faster than &lt;code>handled&lt;/code>, NGINX is taking connections from the kernel and then discarding them. This gap is a leading indicator of connection-slot or file-descriptor exhaustion. It often starts increasing minutes before the system hits the hard wall.&lt;/p></description></item><item><title>NGINX limit_req burst and nodelay tuning: rate limiting without blocking real users</title><link>https://www.netdata.cloud/guides/nginx/nginx-limit-req-burst-tuning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-limit-req-burst-tuning/</guid><description>&lt;h1 id="nginx-limit_req-burst-and-nodelay-tuning-rate-limiting-without-blocking-real-users">NGINX limit_req burst and nodelay tuning: rate limiting without blocking real users&lt;/h1>
&lt;p>Most production nginx rate limiting configs fall into two camps: no burst at all, which rejects legitimate traffic during harmless spikes, or burst without nodelay, which queues real users into artificial delays that mimic upstream slowness. Neither is what you want. The &lt;code>limit_req&lt;/code> module implements a leaky bucket at millisecond granularity, and the interaction between &lt;code>burst&lt;/code> and &lt;code>nodelay&lt;/code> determines whether a request is delayed, rejected, or forwarded immediately. Understanding that interaction, and sizing the shared memory zone to match your traffic profile, is the difference between rate limiting that protects upstreams and rate limiting that creates incidents during normal user behavior.&lt;/p></description></item><item><title>nginx limiting requests, excess -- understanding limit_req rejections</title><link>https://www.netdata.cloud/guides/nginx/nginx-limiting-requests-excess/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-limiting-requests-excess/</guid><description>&lt;h1 id="nginx-limiting-requests-excess----understanding-limit_req-rejections">nginx limiting requests, excess &amp;ndash; understanding limit_req rejections&lt;/h1>
&lt;p>When &lt;code>[error] ... limiting requests, excess&lt;/code> appears in nginx error logs alongside 503 responses in access logs, determine whether you are under attack, misconfigured, or out of shared memory. The &lt;code>ngx_http_limit_req_module&lt;/code> implements a leaky bucket rate limiter. Its interaction with &lt;code>burst&lt;/code>, &lt;code>nodelay&lt;/code>, and shared memory sizing determines whether you reject malicious traffic, delay legitimate users, or silently stop enforcing limits.&lt;/p>
&lt;h2 id="what-it-is-and-why-it-matters">What it is and why it matters&lt;/h2>
&lt;p>&lt;code>limit_req&lt;/code> is nginx&amp;rsquo;s request-level rate limiter. It uses a shared memory zone, configured via &lt;code>limit_req_zone&lt;/code>, to track request rates per key, typically &lt;code>$binary_remote_addr&lt;/code>. The zone is mapped into every worker process. When a request arrives, nginx checks the key&amp;rsquo;s current rate against the configured limit. Depending on &lt;code>burst&lt;/code> and &lt;code>nodelay&lt;/code>, it delays the request, rejects it, or processes it immediately.&lt;/p></description></item><item><title>NGINX listen queue overflow: somaxconn, backlog, and silent connection drops</title><link>https://www.netdata.cloud/guides/nginx/nginx-listen-queue-overflow/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-listen-queue-overflow/</guid><description>&lt;h1 id="nginx-listen-queue-overflow-somaxconn-backlog-and-silent-connection-drops">NGINX listen queue overflow: somaxconn, backlog, and silent connection drops&lt;/h1>
&lt;p>Clients report intermittent connection timeouts. Your load balancer health checks pass. NGINX error logs are clean and access logs show no 5xx spikes. The issue is not in NGINX workers or upstream applications. It is in the kernel accept queue.&lt;/p>
&lt;p>When the accept queue fills, the kernel drops new connections silently. NGINX never sees them, so it logs nothing. Evidence is client-side timeouts and the kernel counter &lt;code>TcpExtListenOverflows&lt;/code>.&lt;/p></description></item><item><title>NGINX log disk full: when logging silently stops and how to recover</title><link>https://www.netdata.cloud/guides/nginx/nginx-log-disk-full/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-log-disk-full/</guid><description>&lt;h1 id="nginx-log-disk-full-when-logging-silently-stops-and-how-to-recover">NGINX log disk full: when logging silently stops and how to recover&lt;/h1>
&lt;p>During an incident, upstream latency climbs and 5xx errors appear. You run &lt;code>tail -f /var/log/nginx/error.log&lt;/code> and the cursor sits there. The last entry is hours old. Requests still return 200s. The server is serving, but it has stopped logging. Disk utilization shows &lt;code>/var/log&lt;/code> at 100 percent.&lt;/p>
&lt;p>This is the NGINX log disk-full failure mode. The process never signals the client or the operator that it can no longer write diagnostics. Visibility evaporates when it is most needed.&lt;/p></description></item><item><title>NGINX monitoring checklist: the signals every production server needs</title><link>https://www.netdata.cloud/guides/nginx/nginx-monitoring-checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-monitoring-checklist/</guid><description>&lt;h1 id="nginx-monitoring-checklist-the-signals-every-production-server-needs">NGINX monitoring checklist: the signals every production server needs&lt;/h1>
&lt;p>NGINX is an event-driven, single-threaded-per-worker process. Most production failures follow predictable patterns: connection exhaustion, backend cascades, file descriptor limits, or silent kernel-level drops. This article maps the signals that expose those failures into four cumulative maturity levels: Survival, Operational, Mature, and Expert. Use it to audit your current coverage or to justify instrumentation work before the next incident.&lt;/p>
&lt;p>Each level adds depth. Survival answers &amp;ldquo;Is it up?&amp;rdquo; Operational answers &amp;ldquo;Is it healthy?&amp;rdquo; Mature adds leading indicators. Expert adds the signals you instrument after your third postmortem. The tables below list each signal, why it matters, and the threshold that should trigger a response.&lt;/p></description></item><item><title>NGINX monitoring maturity model: from survival to expert</title><link>https://www.netdata.cloud/guides/nginx/nginx-monitoring-maturity-model/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-monitoring-maturity-model/</guid><description>&lt;h1 id="nginx-monitoring-maturity-model-from-survival-to-expert">NGINX monitoring maturity model: from survival to expert&lt;/h1>
&lt;p>nginx exposes exactly seven scalars through &lt;code>stub_status&lt;/code>. Latency distributions, upstream health, cache efficiency, and kernel-level drops live in access logs, error logs, or OS counters. Teams that collect only the stub_status numbers assume they have visibility. They do not.&lt;/p>
&lt;p>This article defines four monitoring maturity levels. Level 1 tells you if nginx is alive. Level 2 tells you if it is healthy. Level 3 gives you leading indicators of saturation. Level 4 exposes the blind spots that only appear after repeated incidents. Use these levels to audit your current coverage and decide which signals to add next.&lt;/p></description></item><item><title>nginx no live upstreams while connecting to upstream: what it means</title><link>https://www.netdata.cloud/guides/nginx/nginx-no-live-upstreams/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-no-live-upstreams/</guid><description>&lt;h1 id="nginx-no-live-upstreams-while-connecting-to-upstream-what-it-means">nginx no live upstreams while connecting to upstream: what it means&lt;/h1>
&lt;p>When nginx logs &lt;code>no live upstreams while connecting to upstream&lt;/code>, every server in the affected upstream block is marked unavailable. The proxied request has no eligible backend, so nginx returns 502 Bad Gateway. This is not an nginx defect; it signals that all backends have failed open-source nginx&amp;rsquo;s passive health checks, or a network partition has made them unreachable from the nginx host.&lt;/p></description></item><item><title>NGINX old worker processes accumulating after reload: worker_shutdown_timeout</title><link>https://www.netdata.cloud/guides/nginx/nginx-old-worker-processes-accumulating/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-old-worker-processes-accumulating/</guid><description>&lt;h1 id="nginx-old-worker-processes-accumulating-after-reload-worker_shutdown_timeout">NGINX old worker processes accumulating after reload: worker_shutdown_timeout&lt;/h1>
&lt;p>After &lt;code>nginx -s reload&lt;/code>, worker process count climbs above &lt;code>worker_processes&lt;/code>. Memory and file descriptor usage grow. The workers are not crashing; they are old generations waiting for long-lived connections to close.&lt;/p>
&lt;p>This pattern is normal in small doses. During a reload, the master keeps old workers alive until active connections drain. Without a shutdown deadline, a single WebSocket, gRPC stream, or long-polling connection can pin an old worker indefinitely. In environments that reload frequently, such as Kubernetes ingress controllers reacting to endpoint changes, accumulation becomes a resource leak that can exhaust memory or file descriptors.&lt;/p></description></item><item><title>NGINX proxy buffer spill to disk: proxy_buffers and temp file latency</title><link>https://www.netdata.cloud/guides/nginx/nginx-proxy-buffer-spill-to-disk/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-proxy-buffer-spill-to-disk/</guid><description>&lt;h1 id="nginx-proxy-buffer-spill-to-disk-proxy_buffers-and-temp-file-latency">NGINX proxy buffer spill to disk: proxy_buffers and temp file latency&lt;/h1>
&lt;p>You notice some proxied requests are crawling. Upstream logs show sub-50 ms response times. The network path is clean. The nginx error log is quiet. In the access log, however, &lt;code>$request_time&lt;/code> is ten times larger than &lt;code>$upstream_response_time&lt;/code>. For large responses, this gap is the signature of proxy buffer spill.&lt;/p>
&lt;p>When an upstream response exceeds the memory buffers allocated by &lt;code>proxy_buffers&lt;/code>, nginx writes the overflow to a temporary file under &lt;code>proxy_temp_path&lt;/code> and reads it back later. Because the log message for this event is emitted at debug level only, the delay is silent. Standard upstream monitoring gives no hint; the delay hides entirely inside nginx.&lt;/p></description></item><item><title>NGINX proxy buffer tuning: proxy_buffers, proxy_buffer_size, and busy buffers</title><link>https://www.netdata.cloud/guides/nginx/nginx-proxy-buffer-tuning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-proxy-buffer-tuning/</guid><description>&lt;h1 id="nginx-proxy-buffer-tuning-proxy_buffers-proxy_buffer_size-and-busy-buffers">NGINX proxy buffer tuning: proxy_buffers, proxy_buffer_size, and busy buffers&lt;/h1>
&lt;p>When &lt;code>proxy_buffering&lt;/code> is &lt;code>on&lt;/code> (the default), NGINX absorbs the upstream response in memory before sending it to the client. This shields backends from slow clients and enables compression, but three directives control it: &lt;code>proxy_buffer_size&lt;/code> for headers, &lt;code>proxy_buffers&lt;/code> for the body, and &lt;code>proxy_busy_buffers_size&lt;/code> for the in-flight flush window. Misconfiguration causes 502s, silent disk spills, and reload failures.&lt;/p>
&lt;p>The defaults are modest: eight body buffers of one memory page each, and one header page (typically 4K or 8K). That works for static sites and small JSON, but it fails for modern workloads: APIs with large JWT tokens in headers, bulk exports returning multi-megabyte JSON, and Server-Sent Events streams. Undersized body buffers spill to disk. Undersized header buffers return 502. Invalid &lt;code>proxy_busy_buffers_size&lt;/code> values prevent NGINX from starting or reloading.&lt;/p></description></item><item><title>NGINX proxy cache hit rate is low: measuring and improving it</title><link>https://www.netdata.cloud/guides/nginx/nginx-cache-hit-rate-low/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-cache-hit-rate-low/</guid><description>&lt;h1 id="nginx-proxy-cache-hit-rate-is-low-measuring-and-improving-it">NGINX proxy cache hit rate is low: measuring and improving it&lt;/h1>
&lt;p>Low NGINX proxy cache hit rate shows up as upstream CPU climbing or origin traffic higher than expected. Access logs show MISS and BYPASS where you expect HIT. When caching fails, every request reaches the backend, adding latency and load. The symptom is usually a gradual slide from 85% to 40% over a day, or a collapse to zero after a deployment or restart. Root cause is often configuration drift: a new header, a changed query parameter, or a keys_zone sized for last year&amp;rsquo;s traffic. Diagnose by measuring which cache status dominates, then trace that status back to the directive or upstream behavior that produces it.&lt;/p></description></item><item><title>NGINX proxy_cache not caching: why responses bypass the cache</title><link>https://www.netdata.cloud/guides/nginx/nginx-proxy-cache-not-caching/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-proxy-cache-not-caching/</guid><description>&lt;h1 id="nginx-proxy_cache-not-caching-why-responses-bypass-the-cache">NGINX proxy_cache not caching: why responses bypass the cache&lt;/h1>
&lt;p>After enabling &lt;code>proxy_cache&lt;/code> and defining the cache path, upstreams still take every hit. Access logs show &lt;code>$upstream_cache_status&lt;/code> as &lt;code>BYPASS&lt;/code> or &lt;code>MISS&lt;/code>, hit rate stays near zero, and nothing appears in the error log. NGINX applies a strict request-phase and response-phase decision tree before anything enters the cache. If any condition fails, the response is never stored. The symptom looks like upstream overload, but the root cause is usually a directive, a header, or a missing validity window.&lt;/p></description></item><item><title>NGINX rate limiting returns 503 not 429: limit_req_status explained</title><link>https://www.netdata.cloud/guides/nginx/nginx-rate-limiting-503-not-429/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-rate-limiting-503-not-429/</guid><description>&lt;h1 id="nginx-rate-limiting-returns-503-not-429-limit_req_status-explained">NGINX rate limiting returns 503 not 429: limit_req_status explained&lt;/h1>
&lt;p>When &lt;code>limit_req&lt;/code> rejects a request, nginx returns 503 by default. This is the same code used for genuine capacity exhaustion, so a 503 spike pages the on-call rotation even when the upstream is healthy and the infrastructure is fine. Changing &lt;code>limit_req_status&lt;/code> to 429 is one directive, but the implications for alerting, monitoring, and client behavior are not trivial.&lt;/p>
&lt;h2 id="what-it-is-and-why-it-matters">What it is and why it matters&lt;/h2>
&lt;p>The &lt;code>limit_req_status&lt;/code> directive sets the HTTP status code returned when &lt;code>limit_req&lt;/code> rejects a request. The companion directive &lt;code>limit_conn_status&lt;/code> does the same for connection limits enforced by &lt;code>limit_conn&lt;/code>. Both default to 503.&lt;/p></description></item><item><title>nginx recv() failed (104: Connection reset by peer) while reading from upstream</title><link>https://www.netdata.cloud/guides/nginx/nginx-connection-reset-by-peer/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-connection-reset-by-peer/</guid><description>&lt;h1 id="nginx-recv-failed-104-connection-reset-by-peer-while-reading-from-upstream">nginx recv() failed (104: Connection reset by peer) while reading from upstream&lt;/h1>
&lt;p>You tail the nginx error log and see this:&lt;/p>
&lt;pre tabindex="0">&lt;code>[error] ... recv() failed (104: Connection reset by peer) while reading response header from upstream
&lt;/code>&lt;/pre>&lt;p>The client gets a 502 Bad Gateway. The error is not a configuration syntax problem, and the service was working five minutes ago. This message means the upstream server sent a TCP RST while nginx was mid-read on an upstream connection. The reset originates from the backend or from a network middlebox between nginx and the backend. It does not come from nginx itself, and it does not come from the client.&lt;/p></description></item><item><title>NGINX reload not applying config: why old workers keep serving</title><link>https://www.netdata.cloud/guides/nginx/nginx-reload-not-applying-config/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-reload-not-applying-config/</guid><description>&lt;h1 id="nginx-reload-not-applying-config-why-old-workers-keep-serving">NGINX reload not applying config: why old workers keep serving&lt;/h1>
&lt;p>You pushed a config change, ran &lt;code>nginx -s reload&lt;/code>, and moved on. Hours later, the new certificate is not being served, the updated upstream is not receiving traffic, or the tightened rate limit never took effect. NGINX did not stop running, but the reload never applied. This is the silent rollback: when a reload fails validation, the master keeps the previous configuration active and old workers continue serving. Even when validation passes, old workers can remain alive for hours if long-lived connections prevent them from draining and &lt;code>worker_shutdown_timeout&lt;/code> is not set. This guide shows how to confirm the failure, find the root cause, and prevent config drift from going undetected.&lt;/p></description></item><item><title>NGINX slow requests: from access log to root cause</title><link>https://www.netdata.cloud/guides/nginx/nginx-slow-requests/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-slow-requests/</guid><description>&lt;h1 id="nginx-slow-requests-from-access-log-to-root-cause">NGINX slow requests: from access log to root cause&lt;/h1>
&lt;p>Elevated &lt;code>$request_time&lt;/code> in access logs does not mean the upstream is slow. The variable measures the full lifecycle: from reading the first client byte through sending the last response byte. That includes client upload, upstream wait, nginx processing, and client download. Blaming the backend by reflex is the most common nginx latency mistake.&lt;/p>
&lt;p>To split the time accurately, confirm your &lt;code>log_format&lt;/code> includes &lt;code>$request_time&lt;/code>, &lt;code>$upstream_response_time&lt;/code>, &lt;code>$upstream_connect_time&lt;/code>, and &lt;code>$upstream_header_time&lt;/code>.&lt;/p></description></item><item><title>NGINX slowloris and slow-client attacks: detection and mitigation</title><link>https://www.netdata.cloud/guides/nginx/nginx-slowloris-attack/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-slowloris-attack/</guid><description>&lt;h1 id="nginx-slowloris-and-slow-client-attacks-detection-and-mitigation">NGINX slowloris and slow-client attacks: detection and mitigation&lt;/h1>
&lt;p>You check &lt;code>stub_status&lt;/code> and the Reading count is triple its normal value and not dropping. Requests per second has collapsed to near zero. Active connections are climbing toward &lt;code>worker_connections * worker_processes&lt;/code> while worker CPU stays idle. This is not a backend slowdown. It is a slowloris or slow-client attack: connections open faster than they complete, and NGINX waits for data that arrives one byte at a time.&lt;/p></description></item><item><title>NGINX SSL certificate expired: detection and emergency renewal</title><link>https://www.netdata.cloud/guides/nginx/nginx-ssl-certificate-expired/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-ssl-certificate-expired/</guid><description>&lt;h1 id="nginx-ssl-certificate-expired-detection-and-emergency-renewal">NGINX SSL certificate expired: detection and emergency renewal&lt;/h1>
&lt;p>An expired SSL certificate on NGINX is an immediate outage, not gradual degradation. Browsers and API clients reject the connection at the TLS handshake, often before NGINX logs anything useful. The fix is rarely as simple as running a renewal script again. Verify what is on disk, confirm the running configuration is using it, and force a reload so workers load the new certificate.&lt;/p></description></item><item><title>NGINX SSL session cache: improving TLS resumption and cutting CPU</title><link>https://www.netdata.cloud/guides/nginx/nginx-ssl-session-cache/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-ssl-session-cache/</guid><description>&lt;h1 id="nginx-ssl-session-cache-improving-tls-resumption-and-cutting-cpu">NGINX SSL session cache: improving TLS resumption and cutting CPU&lt;/h1>
&lt;p>TLS handshakes are the most CPU-intensive routine operation in nginx. A worker terminating RSA-2048 TLS can handle only a few hundred full handshakes per second, compared to tens of thousands of plain HTTP requests. In production, every reconnecting client that repeats a full handshake wastes CPU and adds latency. The &lt;code>ssl_session_cache&lt;/code> directive exists to eliminate that waste by allowing session resumption across connections. Yet many configurations either omit it, under-size it, or misunderstand how TLS 1.3 changes resumption behavior. This article explains the mechanism, sizing, and the signals that tell you whether your cache is working.&lt;/p></description></item><item><title>nginx SSL_do_handshake() failed — diagnosing TLS handshake errors</title><link>https://www.netdata.cloud/guides/nginx/nginx-ssl-handshake-failed/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-ssl-handshake-failed/</guid><description>&lt;h1 id="nginx-ssl_do_handshake-failed--diagnosing-tls-handshake-errors">nginx SSL_do_handshake() failed — diagnosing TLS handshake errors&lt;/h1>
&lt;p>You see &lt;code>[crit]&lt;/code> or &lt;code>[error]&lt;/code> entries for &lt;code>SSL_do_handshake() failed&lt;/code> in &lt;code>/var/log/nginx/error.log&lt;/code>. The message might involve a client connecting to nginx, or nginx connecting to an upstream server. These errors mean the TLS negotiation never completed, so no application data was exchanged. The impact ranges from a few browsers showing security warnings to all proxied traffic returning 502 Bad Gateway.&lt;/p>
&lt;p>Before chasing certificates, determine which side of a connection is failing. nginx logs two variants: &lt;code>while SSL handshaking to client&lt;/code> and &lt;code>while SSL handshaking to upstream&lt;/code>. The first affects visitors hitting your server directly. The second affects nginx as a reverse proxy calling a backend over HTTPS. The symptoms, root causes, and fixes are different.&lt;/p></description></item><item><title>NGINX SSL/TLS handshake CPU saturation: detection and tuning</title><link>https://www.netdata.cloud/guides/nginx/nginx-ssl-handshake-cpu-saturation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-ssl-handshake-cpu-saturation/</guid><description>&lt;h1 id="nginx-ssltls-handshake-cpu-saturation-detection-and-tuning">NGINX SSL/TLS handshake CPU saturation: detection and tuning&lt;/h1>
&lt;p>NGINX latency climbs while requests per second flatline. Worker processes are pinned near 100% CPU, yet active connections are nowhere near the &lt;code>worker_connections&lt;/code> limit. Access logs show fast upstream response times, but &lt;code>$request_time&lt;/code> is an order of magnitude larger. The bottleneck is not the network, disk, or backends: it is the TLS handshake.&lt;/p>
&lt;p>When workers burn CPU on cryptography, the single-threaded event loop has no time left for request processing. Every new TCP connection that requires a full SSL handshake adds asymmetric crypto workload. If clients do not resume sessions and the connection rate is high, throughput collapses even though the machine has plenty of idle connection slots. This guide shows how to detect, diagnose, and tune for SSL handshake CPU saturation.&lt;/p></description></item><item><title>NGINX upstream keepalive: eliminating per-request TCP and TLS overhead</title><link>https://www.netdata.cloud/guides/nginx/nginx-upstream-keepalive/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-upstream-keepalive/</guid><description>&lt;h1 id="nginx-upstream-keepalive-eliminating-per-request-tcp-and-tls-overhead">NGINX upstream keepalive: eliminating per-request TCP and TLS overhead&lt;/h1>
&lt;p>Every proxied request that opens a fresh TCP connection burns latency on the handshake and, if the upstream uses HTTPS, on TLS negotiation. At low volume this cost is invisible. At production throughput it becomes a measurable tax on every request, and at extreme scale it can exhaust the kernel&amp;rsquo;s ephemeral port range and bury the host in TIME_WAIT sockets. For HTTPS upstreams, the CPU cost of TLS handshakes across thousands of requests per second consumes worker cycles that could be spent proxying traffic.&lt;/p></description></item><item><title>nginx upstream prematurely closed connection while reading response header</title><link>https://www.netdata.cloud/guides/nginx/nginx-upstream-prematurely-closed-connection/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-upstream-prematurely-closed-connection/</guid><description>&lt;h1 id="nginx-upstream-prematurely-closed-connection-while-reading-response-header">nginx upstream prematurely closed connection while reading response header&lt;/h1>
&lt;p>&lt;code>upstream prematurely closed connection while reading response header from upstream&lt;/code> means the upstream server closed the TCP socket while nginx was still reading response headers. This produces a 502 Bad Gateway. Unlike a timeout, the upstream actively terminated the connection.&lt;/p>
&lt;p>The root cause is typically on the backend: a crash, worker recycle, request size limit, or stale keepalive connection the backend closed while nginx tried to reuse it. nginx retries the request on another backend only if &lt;code>proxy_next_upstream&lt;/code> includes &lt;code>error&lt;/code> (the default for idempotent methods). Retries improve availability but do not fix the underlying issue.&lt;/p></description></item><item><title>nginx upstream sent too big header while reading response header from upstream</title><link>https://www.netdata.cloud/guides/nginx/nginx-upstream-sent-too-big-header/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-upstream-sent-too-big-header/</guid><description>&lt;h1 id="nginx-upstream-sent-too-big-header-while-reading-response-header-from-upstream">nginx upstream sent too big header while reading response header from upstream&lt;/h1>
&lt;p>The error log contains &lt;code>upstream sent too big header while reading response header from upstream&lt;/code>. Clients receive 502 Bad Gateway. This is not an upstream crash or network timeout. It is a hard size limit: an upstream server is sending response headers larger than the fixed buffer nginx allocates for reading them, so nginx aborts the request and returns 502.&lt;/p></description></item><item><title>nginx upstream timed out (110: Connection timed out) while connecting/reading</title><link>https://www.netdata.cloud/guides/nginx/nginx-upstream-timed-out/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-upstream-timed-out/</guid><description>&lt;h1 id="nginx-upstream-timed-out-110-connection-timed-out-while-connectingreading">nginx upstream timed out (110: Connection timed out) while connecting/reading&lt;/h1>
&lt;p>&lt;code>upstream timed out (110: Connection timed out)&lt;/code> in the nginx error log usually surfaces to clients as a 504 Gateway Timeout. The suffix after the error string tells you which phase failed: connecting, sending, or reading. That phase determines whether you are looking at a dead backend, a network partition, or a retry storm hiding the real problem.&lt;/p>
&lt;p>The defaults are unforgiving. &lt;code>proxy_connect_timeout&lt;/code>, &lt;code>proxy_send_timeout&lt;/code>, and &lt;code>proxy_read_timeout&lt;/code> all default to 60 seconds, and &lt;code>proxy_next_upstream&lt;/code> implicitly retries on &lt;code>error&lt;/code> and &lt;code>timeout&lt;/code>. Retries can mask the root cause while exhausting upstream capacity.&lt;/p></description></item><item><title>NGINX worker_connections and worker_processes: sizing for real traffic</title><link>https://www.netdata.cloud/guides/nginx/nginx-worker-connections-tuning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-worker-connections-tuning/</guid><description>&lt;h1 id="nginx-worker_connections-and-worker_processes-sizing-for-real-traffic">NGINX worker_connections and worker_processes: sizing for real traffic&lt;/h1>
&lt;p>NGINX defaults leave most CPU cores idle and exhaust quickly under load. The real limit is often the OS file descriptor ceiling, which silently overrides the directive.&lt;/p>
&lt;p>Sizing these parameters means understanding the capacity chain: kernel queue, connection slot, file descriptor limit, event loop. This guide provides concrete rules for static and proxy workloads and the signals that reveal when headroom has disappeared.&lt;/p></description></item><item><title>NGINX worker_rlimit_nofile: setting file descriptor limits correctly</title><link>https://www.netdata.cloud/guides/nginx/nginx-worker-rlimit-nofile/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-worker-rlimit-nofile/</guid><description>&lt;h1 id="nginx-worker_rlimit_nofile-setting-file-descriptor-limits-correctly">NGINX worker_rlimit_nofile: setting file descriptor limits correctly&lt;/h1>
&lt;p>nginx file descriptor exhaustion is a silent failure mode. Existing connections continue to be served, but new connections queue in the kernel backlog and are eventually dropped. The client sees a timeout, while nginx error logs may show nothing until the limit is hit.&lt;/p>
&lt;p>&lt;code>worker_rlimit_nofile&lt;/code> raises the per-worker file descriptor limit above conservative operating system defaults. It does not operate in isolation. It sits inside a layered stack of kernel parameters, systemd service limits, container runtime defaults, and PAM session policies. A value written into &lt;code>nginx.conf&lt;/code> is only effective if the master process inherits a hard limit at least as high, and the kernel ceiling permits it. If any layer caps the limit below your intended value, workers inherit that lower ceiling and your tuning is silently ignored.&lt;/p></description></item><item><title>nginx: a client request body is buffered to a temporary file — what it means</title><link>https://www.netdata.cloud/guides/nginx/nginx-buffered-to-temporary-file/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-buffered-to-temporary-file/</guid><description>&lt;h1 id="nginx-a-client-request-body-is-buffered-to-a-temporary-file--what-it-means">nginx: a client request body is buffered to a temporary file — what it means&lt;/h1>
&lt;p>You are tailing the nginx error log during a latency investigation and see the line: a client request body is buffered to a temporary file. It is logged at [warn], not [error], so it is easy to ignore. But the message means a request body has exceeded the in-memory buffer and nginx is now writing that data to disk. On a busy reverse proxy or file-upload endpoint, this behavior can add hundreds of milliseconds or seconds of latency before your upstream application receives the payload. It also consumes file descriptors and disk I/O capacity without ever surfacing as a 5xx status code.&lt;/p></description></item><item><title>nginx: bind() to 0.0.0.0:80 failed (98: Address already in use)</title><link>https://www.netdata.cloud/guides/nginx/nginx-address-already-in-use/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-address-already-in-use/</guid><description>&lt;h1 id="nginx-bind-to-000080-failed-98-address-already-in-use">nginx: bind() to 0.0.0.0:80 failed (98: Address already in use)&lt;/h1>
&lt;p>The error log shows &lt;code>[emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)&lt;/code> and the master process exits. During a reload, old workers keep running with the previous configuration, so users may not notice immediately. During system boot or a manual start, the service is down.&lt;/p>
&lt;p>Error 98 is &lt;code>EADDRINUSE&lt;/code>. The nginx master binds listening sockets before forking workers. If the kernel reports port 80 is occupied, nginx cannot start or apply the new configuration. The holder might be a different service, a stale nginx master after a crash, or another nginx instance. Inside the same configuration, conflicting socket options for the same address:port can also trigger the error.&lt;/p></description></item><item><title>nginx: configuration file test failed - finding the syntax error</title><link>https://www.netdata.cloud/guides/nginx/nginx-configuration-file-test-failed/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-configuration-file-test-failed/</guid><description>&lt;h1 id="nginx-configuration-file-test-failed---finding-the-syntax-error">nginx: configuration file test failed - finding the syntax error&lt;/h1>
&lt;p>An &lt;code>nginx -t&lt;/code> or &lt;code>nginx -s reload&lt;/code> ending with &lt;code>nginx: configuration file /path/to/nginx.conf test failed&lt;/code> means the configuration tree is syntactically invalid or references a missing file. The master process rejects the change, so the running server continues with the previous working configuration. That prevents an outage, but your intended change is silently inactive. Read the exact error message, map it to the real source, fix it, and validate with &lt;code>nginx -t&lt;/code> before reloading.&lt;/p></description></item><item><title>nginx: could not build server_names_hash -- server_names_hash_bucket_size</title><link>https://www.netdata.cloud/guides/nginx/nginx-server-names-hash-bucket-size/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-server-names-hash-bucket-size/</guid><description>&lt;h1 id="nginx-could-not-build-server_names_hash----server_names_hash_bucket_size">nginx: could not build server_names_hash &amp;ndash; server_names_hash_bucket_size&lt;/h1>
&lt;p>Running &lt;code>nginx -t&lt;/code> or &lt;code>nginx -s reload&lt;/code> stops with &lt;code>[emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32&lt;/code>. Alternatively, nginx starts but logs &lt;code>[warn] could not build optimal server_names_hash, you should increase either server_names_hash_max_size: 512 or server_names_hash_bucket_size: 64&lt;/code>.&lt;/p>
&lt;p>This error means your configuration has exceeded a limit in nginx&amp;rsquo;s server name hashing logic. nginx builds this hash at configuration load time, not at request time. If the build fails, the configuration test fails. If the build succeeds but is suboptimal, nginx starts with degraded lookup performance. Both directives, &lt;code>server_names_hash_bucket_size&lt;/code> and &lt;code>server_names_hash_max_size&lt;/code>, are valid only inside the &lt;code>http&lt;/code> context.&lt;/p></description></item><item><title>nginx: no resolver defined to resolve - dynamic upstream DNS</title><link>https://www.netdata.cloud/guides/nginx/nginx-no-resolver-defined/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-no-resolver-defined/</guid><description>&lt;h1 id="nginx-no-resolver-defined-to-resolve---dynamic-upstream-dns">nginx: no resolver defined to resolve - dynamic upstream DNS&lt;/h1>
&lt;p>502 Bad Gateway responses paired with &lt;code>no resolver defined to resolve example.com&lt;/code> in the error log mean &lt;code>proxy_pass&lt;/code> uses a variable - for example, &lt;code>proxy_pass http://$backend;&lt;/code> - and the enclosing context has no &lt;code>resolver&lt;/code> directive.&lt;/p>
&lt;p>With a literal &lt;code>proxy_pass&lt;/code>, nginx resolves the upstream hostname once at startup or reload and caches the result indefinitely. It never queries DNS again until restart or reload. With a variable-based &lt;code>proxy_pass&lt;/code>, nginx resolves the hostname at request time through its internal async resolver. Without a &lt;code>resolver&lt;/code> directive, the lookup fails immediately and returns 502.&lt;/p></description></item><item><title>nginx: too many open files - diagnosing file descriptor exhaustion</title><link>https://www.netdata.cloud/guides/nginx/nginx-too-many-open-files/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-too-many-open-files/</guid><description>&lt;h1 id="nginx-too-many-open-files---diagnosing-file-descriptor-exhaustion">nginx: too many open files - diagnosing file descriptor exhaustion&lt;/h1>
&lt;p>After a traffic spike, the error log shows &lt;code>accept4() failed (24: Too many open files)&lt;/code>, then goes silent. Existing connections still serve, but new ones cannot land.&lt;/p>
&lt;p>File descriptor exhaustion is a hard failure. Once the limit is hit, nginx cannot accept new connections, open upstream sockets, or write to the error log. Default OS limits of 1024 are too low for production reverse proxies. Each proxied request consumes at least two FDs, and idle keepalive connections hold them indefinitely. The effective limit is the lower of &lt;code>worker_rlimit_nofile&lt;/code> and the OS hard limit enforced by systemd or the container runtime.&lt;/p></description></item><item><title>nginx: worker_connections are not enough — causes and fixes</title><link>https://www.netdata.cloud/guides/nginx/nginx-worker-connections-are-not-enough/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/nginx/nginx-worker-connections-are-not-enough/</guid><description>&lt;h1 id="nginx-worker_connections-are-not-enough--causes-and-fixes">nginx: worker_connections are not enough — causes and fixes&lt;/h1>
&lt;p>Your error log shows &lt;code>worker_connections are not enough while connecting to upstream&lt;/code>. New clients time out while existing connections may still work. This is a hard capacity cliff: once a worker exhausts its connection slots, it cannot accept new connections until a slot frees. The default limit is 512 per worker, not 1024, and in reverse-proxy mode each request consumes at least two slots. Raising the number is often the first reaction, but if a slow backend is holding connections open, the slots will fill again no matter how high you set the limit.&lt;/p></description></item></channel></rss>