# Rate Limiting, Connection Limits and Request Size — Nginx

Source: https://www.skillbyai.com/en/nginx/x-limits

> Protect applications with limit_req, limit_conn and body size limits.

## Keeping abusive traffic out

**`limit_req_zone`** defines a rate limit keyed by a variable, usually `$binary_remote_addr` (the client IP in compact form), with a shared memory zone and a rate such as `10r/s`. **`limit_req zone=name burst=20 nodelay;`** applies it: requests beyond the rate are queued up to the **burst** size, and with **`nodelay`** burst requests are served immediately while still counting against the limit, which suits APIs. Excess requests are rejected, by default with 503; set **`limit_req_status 429;`** for the correct "Too Many Requests" status. Use different zones for different sensitivities: a strict limit on `/login` against brute force, a looser one on the API. **`limit_conn`** caps concurrent connections per key, useful for downloads. **`client_max_body_size`** (default 1 MB) limits request bodies; raise it only where uploads need it. Timeouts such as `client_body_timeout` and `client_header_timeout` reduce the impact of slow-request attacks.

## Rate limiting with a burst allowance

Requests flow at the allowed rate; a burst bucket absorbs short spikes; the rest are rejected.

![A funnel with a small reservoir above a narrow spout; arrows above the funnel overflow sideways into a reject bin.](assets/figures/nginx/section-7-map.svg) — Figure 7.1 — limit_req with a burst queue.

## Different limits for login and API

Strict on authentication, generous on normal API traffic.

```nginx
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=api:20m   rate=20r/s;
limit_conn_zone $binary_remote_addr zone=perip:10m;

server {
    limit_req_status 429;
    limit_conn_status 429;
    client_max_body_size 2m;

    location = /login {
        limit_req zone=login burst=5;            # 5 per minute, small queue
        proxy_pass http://app_backend;
    }

    location /api/ {
        limit_req zone=api burst=40 nodelay;
        proxy_pass http://api_backend;
    }

    location /downloads/ {
        limit_conn perip 2;                      # at most 2 parallel downloads per IP
        limit_rate 2m;                           # 2 MB/s per connection
    }

    location /upload/ {
        client_max_body_size 50m;                # only here
        proxy_pass http://app_backend;
    }
}
```

## Limit by the real client IP

Behind a CDN or load balancer, every request appears to come from a few proxy IPs, so a per-IP limit throttles everyone together. Configure `real_ip` first, or limit by an API key header instead.

**Quiz:** What does `nodelay` change in `limit_req zone=api burst=40 nodelay;`?

- [x] Burst requests are served immediately instead of being delayed to match the rate
- [ ] It disables the limit
- [ ] It returns 429 for every request
- [ ] It only applies to POST requests

*Answer:* Burst requests are served immediately instead of being delayed to match the rate. Without nodelay, burst requests are queued and released at the configured rate.
