NGINX Error Guide: 'worker_connections are not enough' Connection Pool Exhaustion
Fix NGINX 'worker_connections are not enough' by raising worker_connections in the events block and aligning the file descriptor limit on each worker.
- #nginx
- #troubleshooting
- #errors
- #limits
Exact Error Message
When NGINX runs out of connection slots inside a worker process, it logs an [alert] to the error log. As a reverse proxy, the message usually mentions the upstream:
2026/06/27 18:05:51 [alert] 2841#2841: *204815 worker_connections are not enough while connecting to upstream, client: 203.0.113.7, server: app.example.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:9000/", host: "app.example.com"
You may also see the shorter, non-proxy variant when NGINX serves files or terminates connections directly:
2026/06/27 18:05:52 [alert] 2841#2841: 1024 worker_connections are not enough
Both come from the same root cause: a single worker process has reached its worker_connections ceiling and cannot accept or open another socket.
What the Error Means
NGINX is event-driven. Each worker process maintains a fixed-size pool of connection slots, sized by the worker_connections directive (default 512, often 1024). A connection slot is consumed by any open socket the worker is managing: an inbound client connection, an outbound upstream connection, a connection to a memcached or FastCGI backend, or a DNS resolver socket.
The critical detail for a reverse proxy is that every proxied request consumes two slots, not one:
- One slot for the client connection (browser to NGINX).
- One slot for the upstream connection (NGINX to your app server).
So a worker configured with worker_connections 1024 can proxy at most 512 simultaneous requests, not 1024. The while connecting to upstream wording tells you NGINX had a client connection in hand, tried to open the second slot for the backend, and found the pool already full.
This is a per-worker limit. The theoretical ceiling for the whole server is:
max_clients = worker_processes * worker_connections
and for a reverse proxy the useful ceiling is roughly half that:
max_proxied_requests ≈ (worker_processes * worker_connections) / 2
Common Causes
worker_connectionsleft at the default. The stock512or1024is fine for a static file server but quickly exhausted behind a busy reverse proxy where each request is doubled.- Traffic spike or slow upstream. If the backend slows down, connections pile up because each one stays open longer, multiplying concurrent slot usage.
- Keepalive connections. Browser keepalive (and upstream keepalive pools) hold slots open between requests, so idle connections still count against the limit.
- The file descriptor limit is lower than
worker_connections. Each connection needs a file descriptor. If the worker’sRLIMIT_NOFILEis belowworker_connections, you hit the fd wall first (a different error) and effectively cap connections early. - Too few worker processes. With
worker_processes 1, all traffic funnels through a single pool. The total capacity is just one worker’s worth of slots.
How to Reproduce the Error
Set an artificially tiny limit and drive concurrent proxied requests through it. In a test config:
events {
worker_connections 4;
}
Reload, then fire more concurrent connections than the pool allows. A quick load generator works:
# 100 concurrent connections, 1000 total, against the proxy
ab -n 1000 -c 100 http://app.example.com/
With only 4 slots per worker (2 usable proxied requests), NGINX will log worker_connections are not enough while connecting to upstream almost immediately. Reset the directive afterward.
Diagnostic Commands
All read-only. Start by confirming what NGINX is actually using, since the effective value can come from an included file:
# Validate config and show where the binary thinks the config lives
sudo nginx -t
# Dump the full, resolved config and grep the relevant directives
sudo nginx -T 2>/dev/null | grep -E 'worker_connections|worker_processes|worker_rlimit_nofile'
Check how many connections the box is currently handling so you can size the new limit against reality:
# Socket summary: total, established, etc.
ss -s
# Count established TCP connections
ss -tan state established | wc -l
Confirm the alerts in the journal and check timing against traffic spikes:
journalctl -u nginx --since "1 hour ago" | grep -i "worker_connections"
Inspect the per-worker file descriptor limit. This is the ceiling that worker_connections must respect:
# Soft/hard NOFILE limit for a running worker process
cat /proc/$(pgrep -o nginx)/limits | grep -i "open files"
And confirm your CPU count, since worker_processes auto maps to it:
nproc
If cat /proc/.../limits shows Max open files of, say, 1024 while you want worker_connections 8192, the fd limit is your real bottleneck and must be raised first.
Step-by-Step Resolution
1. Find the current values. Use nginx -T | grep (above) to read the live worker_connections, worker_processes, and any worker_rlimit_nofile.
2. Raise worker_connections in the events block. This directive lives in events {}, not http {}:
events {
worker_connections 4096;
}
Pick a value based on expected concurrency. For a reverse proxy serving N simultaneous requests per worker, you need at least 2 * N slots, plus headroom.
3. Make sure you have enough workers. Let NGINX match cores:
worker_processes auto;
With auto and an 8-core box, worker_connections 4096 gives a theoretical ceiling of 8 * 4096 = 32768 connections, or ~16k concurrent proxied requests.
4. Align the file descriptor limit. worker_connections must be less than or equal to the per-worker file descriptor limit, since every connection consumes one fd. Set it explicitly in the main context so NGINX raises RLIMIT_NOFILE for its workers:
worker_rlimit_nofile 16384;
A good rule of thumb is worker_rlimit_nofile >= 2 * worker_connections to leave room for log files, upstream sockets, and resolver descriptors. If the OS hard limit is lower, also raise it via systemd (LimitNOFILE= in a drop-in for the nginx unit) or /etc/security/limits.conf, otherwise NGINX cannot exceed the system ceiling.
5. Test and reload. worker_connections takes effect on a reload, not a config re-read, so apply it with:
sudo nginx -t && sudo systemctl reload nginx
6. Verify. Re-run cat /proc/$(pgrep -o nginx)/limits to confirm the new fd limit landed on the workers, and watch the error log to confirm the alerts stop under load.
Prevention and Best Practices
- Size for the proxy double-count. Always plan around
2 * concurrent_requestsper worker when NGINX proxies upstreams. - Keep
worker_rlimit_nofileahead ofworker_connections. Treat the fd limit as the hard floor; never setworker_connectionshigher than the worker’s available descriptors. - Use upstream keepalive deliberately. A
keepaliveconnection pool to backends reduces connection churn but holds slots open; account for it in your math. - Monitor established connections over time. Alert when
ss -tan state established | wc -ltrends toward your computed ceiling so you raise limits before the alert fires. Connection-pool exhaustion is a great candidate for an automated alert rule, see the monitoring alerts dashboard. - Fix slow upstreams. Often the real cause is a backend that got slow, multiplying open connections. Address latency, not just the limit.
Related Errors
Too many open files/accept4() failed (24: Too many open files)— this is the file descriptor limit (RLIMIT_NOFILE), a kernel/OS limit, not the NGINX connection-pool limit. They look similar and often co-occur: raisingworker_connectionswithout raisingworker_rlimit_nofilesimply trades one error for the other. Fix the fd limit withworker_rlimit_nofileand the systemLimitNOFILE.upstream timed out (110: Connection timed out) while connecting to upstream— backend is slow or unreachable; slow upstreams are a frequent cause of connection pileups that lead to theworker_connectionsalert.no live upstreams while connecting to upstream— all backends marked down by health checks; unrelated to the pool size but appears in the same proxy log lines.
For more NGINX troubleshooting guides, see the NGINX category.
Frequently Asked Questions
Does worker_connections count both the client and the upstream connection?
Yes. When NGINX acts as a reverse proxy, each request uses two slots from the worker’s pool: one for the inbound client socket and one for the outbound upstream socket. That halves your effective request capacity, so a worker with worker_connections 1024 can handle roughly 512 concurrent proxied requests.
What is the difference between worker_connections are not enough and Too many open files?
worker_connections are not enough means you hit NGINX’s own per-worker connection-pool limit set in the events block. Too many open files means you hit the operating system’s file descriptor limit (RLIMIT_NOFILE). You must keep worker_rlimit_nofile at or above worker_connections, otherwise raising one just exposes the other.
Do I need to restart NGINX after changing worker_connections?
No restart is required; a reload is enough. Run sudo nginx -t && sudo systemctl reload nginx. NGINX spins up new worker processes with the updated pool size and gracefully retires the old ones. A full restart is only needed for some low-level changes like binding new listen sockets.
How high can I set worker_connections?
The practical ceiling is the per-worker file descriptor limit, since every connection needs a descriptor. Set worker_rlimit_nofile first (commonly 2 * worker_connections), make sure the OS hard limit allows it, then raise worker_connections. Values of 4096–16384 per worker are common on busy proxies with adequate fd limits.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.