# Performance Tuning Basics — Nginx

Source: https://www.skillbyai.com/en/nginx/c-tuning

> Tune workers, connections, keepalive and buffers sensibly.

## A few settings that matter

NGINX's defaults are reasonable, and most performance problems lie in the application, but a few settings deserve attention. **`worker_processes auto;`** runs one worker per CPU core. **`worker_connections`** caps connections per worker (including connections to upstreams), so maximum concurrent clients is roughly workers × connections ÷ 2 when proxying; raise the operating system's open-file limit with **`worker_rlimit_nofile`** and the service's `LimitNOFILE` to match. **Client keepalive** (`keepalive_timeout`, `keepalive_requests`) reuses connections from browsers; **upstream keepalive** (`keepalive` in upstream blocks) avoids a new TCP and TLS handshake to the backend for every request. **`sendfile on;`**, `tcp_nopush on;` and `tcp_nodelay on;` speed up file transfer. **`open_file_cache`** caches file descriptors and metadata for frequently served static files. Proxy buffers (`proxy_buffers`, `proxy_buffer_size`) may need increasing for apps that send large headers, such as big cookies or tokens. Measure with a load-testing tool before and after each change.

## A tuned baseline

Values are starting points; measure with your own traffic.

```nginx
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 8192;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 30s;
    keepalive_requests 1000;

    open_file_cache max=10000 inactive=60s;
    open_file_cache_valid 120s;
    open_file_cache_errors on;

    proxy_buffer_size 16k;           # large response headers (cookies, JWTs)
    proxy_buffers 8 16k;
    client_body_buffer_size 128k;
}
```

## "upstream sent too big header" means buffers

This error usually appears when an application sends large cookies or authorization headers. Increase `proxy_buffer_size` (and possibly `proxy_buffers`) rather than turning buffering off.

**Quiz:** Why add `keepalive` to an upstream block?

- [x] To reuse connections to backend servers instead of opening a new one per request
- [ ] To cache responses
- [ ] To enable HTTP/3
- [ ] To compress responses

*Answer:* To reuse connections to backend servers instead of opening a new one per request. Upstream keepalive avoids repeated TCP (and TLS) handshakes to backends.
