> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connection Handling

> NGINX connection handling and tuning guide covering worker processes, keepalive, HTTP versions, sendfile, and TCP socket optimizations for higher throughput and lower latency.

This lesson explains how NGINX handles connections and how to tune key settings for higher throughput and lower latency. We'll cover worker processes and connections, persistent (keepalive) connections for clients and upstreams, HTTP version considerations, and socket-level optimizations like sendfile and TCP options.

Quick overview: NGINX uses a single master process to control multiple worker processes. Each worker runs an event loop that accepts and handles network I/O and client connections independently.

![A diagram titled "Connection Handling" showing a master process coordinating multiple worker processes. Incoming request/response traffic is routed to each worker, and each worker runs an event loop to monitor events.](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Performance/Connection-Handling/connection-handling-master-workers-event-loop.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=bd4475d3bbd7f29ce431a32a0823db19)

## Worker processes and max connections

By default, NGINX chooses one worker process per CPU core (`worker_processes auto;`), which is generally the recommended configuration. Two directives control concurrency at the worker level:

* `worker_processes` — number of NGINX worker processes (recommended: `auto`).
* `worker_connections` — maximum number of connections each worker may open concurrently.

Minimal example:

```nginx theme={null}
worker_processes auto;

events {
    worker_connections 512;
}
```

Approximate maximum simultaneous connections NGINX can handle:

```text theme={null}
max_connections ≈ worker_processes * worker_connections
```

Example: With 4 CPU cores and `worker_connections 512`, you can expect roughly 4 \* 512 = 2048 concurrent connections. Note: `worker_connections` counts all connections handled by a worker (client connections plus upstream/backend connections and any other socket). Always plan for backend connection usage and file descriptor limits.

## Persistent connections (keepalive)

Persistent connections (keepalive) allow clients to reuse the same TCP connection for multiple HTTP requests, avoiding repeated TCP handshakes and reducing CPU and network overhead.

Analogy: Opening a new TCP connection for each resource fetch is like queuing for a separate cup of coffee each time. Keepalive lets you stay at the counter and order multiple cups without re-queuing.

Without keepalive each resource fetch opens a new connection:

![An illustration titled "Without Keep Alive" showing a browser on the left and a server on the right with dashed lines for multiple separate requests/responses. Icons for HTML, XML, JS, CSS and JSON indicate each resource being fetched individually.](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Performance/Connection-Handling/without-keep-alive-separate-requests.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=10e7ab304656e21ab115161b9af74417)

With keepalive the browser can reuse the same connection for multiple resources:

![A simple network diagram titled "With Keep Alive" showing a browser (laptop) on the left and a server (rack) on the right. Dashed arrows between them illustrate transfer of multiple resource files (JS, HTML, JSON, XML, CSS).](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Performance/Connection-Handling/keep-alive-browser-server-resources.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=f9901d625e762aab687318fa2f97d69d)

Key keepalive directives (place inside the `http` block):

* `keepalive_requests` — maximum number of requests allowed on a single keepalive connection (default usually 100).
* `keepalive_timeout` — number of seconds to keep an idle keepalive connection open.

Example:

```nginx theme={null}
http {
    keepalive_requests 100;
    keepalive_timeout 65;
}
```

When NGINX proxies to upstream servers, it can keep idle connections open to backends to avoid repeated connection setup. Use `keepalive` inside an `upstream` block:

```nginx theme={null}
http {
    upstream backend {
        server 10.10.0.101:80;
        server 10.10.0.102:80;
        server 10.10.0.103:80;
        keepalive 32;
    }
}
```

In a `server`/`location` block, enable HTTP/1.1 proxying and allow NGINX to manage the connection header:

```nginx theme={null}
server {
    listen 80;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://backend;
    }
}
```

* `proxy_http_version 1.1;` — ensures proxy requests use HTTP/1.1 (persistent connections require HTTP/1.1+).
* `proxy_set_header Connection "";` — clears the `Connection` header so proxying does not inadvertently disable keepalive.

You can inspect the negotiated HTTP version in your browser DevTools Network tab or with curl:

```bash theme={null}
curl --head https://www.google.com
```

Example output:

```http theme={null}
HTTP/2 200
content-type: text/html; charset=ISO-8859-1
```

## HTTP protocol evolution and impact

A short history of HTTP and how it affects connection handling:

* HTTP/0.9 — minimal protocol, no headers.
* HTTP/1.0 — added status codes and headers.
* HTTP/1.1 — persistent connections, chunked encoding, improved caching.
* HTTP/2 — multiplexing multiple requests/responses over a single connection, header compression, better utilization of a single TCP connection.
* HTTP/3 — runs over QUIC/UDP, improves latency and loss recovery and requires TLS 1.3.

![An illustration titled "HTTP Versions" that shows the evolution of the HTTP protocol as five silhouettes progressing from a hunched, ape-like figure (HTTP 0.9) to a modern upright humanoid (HTTP 3.0). Each figure is labeled with its HTTP version (0.9, 1.0, 1.1, 2.0, 3.0).](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Performance/Connection-Handling/http-evolution-silhouettes-0-9-to-3-0.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=d2769f2d9fb338103941fbadd69cbf92)

Transport layer summary:

* TCP — connection-oriented, reliable, used by HTTP/1.1 and HTTP/2 (though HTTP/2 improvements are at the protocol layer).
* UDP/QUIC — used by HTTP/3 for lower-latency recovery and faster connection establishment.

Adoption varies; many sites use HTTP/2 and HTTP/3 while others remain on HTTP/1.1.

![A slide with two side-by-side line charts titled "HTTP Versions Usage," showing historical usage trends for HTTP/2 (about 34.6%) and HTTP/3 (about 34.0%) across 2024–2025. The graphs plot monthly percentage changes for each protocol.](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Performance/Connection-Handling/http-versions-usage-http2-http3-trends.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=49dea7b78a384fe10eff23f364f259ed)

## Zero-copy file transfer: sendfile

Serving static files benefits from kernel-level zero-copy using `sendfile()`. Instead of copying file data into user-space buffers and then sending to the socket, NGINX can ask the kernel to transfer data directly from disk to the network socket.

Enable sendfile in the `http` block:

```nginx theme={null}
http {
    sendfile on;
}
```

This reduces CPU usage and memory copying when serving static assets.

## TCP socket options: tcp\_nopush and tcp\_nodelay

NGINX exposes socket-level options to control small-packet behavior:

* `tcp_nopush on;` — when using `sendfile`, delays sending response headers until the first body chunk is ready so headers and the first body chunk can be sent in fewer packets. Useful for reducing packet count with large static responses.
* `tcp_nodelay on;` — disables Nagle's algorithm so that small packets are sent immediately (reduces latency for small writes).

Typical configuration:

```nginx theme={null}
http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
}
```

## Quick reference table

| Directive | Purpose | Example |
| - | - | - |
| `worker_processes` | Number of worker processes (usually `auto`) | `worker_processes auto;` |
| `worker_connections` | Max connections per worker | `events { worker_connections 512; }` |
| `keepalive_requests` | Max requests per keepalive connection | `http { keepalive_requests 100; }` |
| `keepalive_timeout` | Seconds to keep idle client connection | `http { keepalive_timeout 65; }` |
| `upstream ... keepalive` | Idle connections to upstream pool | `upstream backend { keepalive 32; }` |
| `proxy_http_version` | Use HTTP/1.1 when proxying (for keepalive) | `proxy_http_version 1.1;` |
| `proxy_set_header Connection ""` | Let NGINX manage connection header | `proxy_set_header Connection "";` |
| `sendfile` | Enable kernel sendfile/zero-copy | `http { sendfile on; }` |
| `tcp_nopush` | Reduce small packet count with sendfile | `tcp_nopush on;` |
| `tcp_nodelay` | Disable Nagle for low-latency small writes | `tcp_nodelay on;` |

## Practical tuning checklist

* Start with `worker_processes auto` and measure.
* Calculate expected max connections and ensure the OS file descriptor limits are high enough.
* Use `keepalive` for upstream pools to reduce backend connection churn.
* Enable `sendfile` when serving static assets.
* Use `tcp_nopush` with `sendfile` and `tcp_nodelay` for appropriate latency/throughput tradeoffs.
* Test with realistic traffic patterns, monitoring CPU, memory, and file descriptor usage.

Be careful when increasing keepalive and worker connection limits: keeping many idle connections consumes file descriptors and memory. Monitor file descriptor limits (`ulimit -n`), CPU, and memory, and tune values according to your workload and testing results.

Clearing or setting the `Connection` header incorrectly in proxying can disable keepalive. Use `proxy_set_header Connection "";` to let NGINX manage connection persistence, and confirm behavior in staging before production.

## References and further reading

* NGINX documentation — [https://nginx.org/en/docs/](https://nginx.org/en/docs/)
* HTTP/2 overview — [https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)
* HTTP/3 and QUIC — [https://datatracker.ietf.org/wg/quic/about/](https://datatracker.ietf.org/wg/quic/about/)
* curl manual/examples — [https://curl.se/docs/manpage.html](https://curl.se/docs/manpage.html)

This concludes the lesson on connection handling and core NGINX tuning options for connections, keepalive, and socket-level optimizations.

> **[Watch Video](https://learn.kodekloud.com/user/courses/nginx-for-beginners/module/4a5db5c4-df5f-4291-84f0-013d1c4ce235/lesson/7ad3d436-d724-42e8-b440-80791ec5f9b5)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.