dkduckkit.dev

nginx limit_req

Rate Limiting

limit_req is the Nginx directive that implements token bucket rate limiting for HTTP requests. It works in conjunction with limit_req_zone, which defines a shared memory zone (the token bucket state) keyed by a variable such as client IP or API key. The rate parameter sets the steady-state refill rate; burst sets the bucket capacity; nodelay processes burst requests immediately rather than queuing them.

Formula

Minimal configuration: limit_req_zone $http_x_api_key zone=api:10m rate=10r/s; server { location /api/ { limit_req zone=api burst=50 nodelay; limit_req_status 429; add_header Retry-After 5 always; } }

Why it matters in practice

limit_req is the most widely deployed rate limiting mechanism on the internet, running in front of millions of APIs. Misconfiguring it — wrong key variable, missing nodelay, wrong burst value — is a common cause of unexpected 429s or, worse, no rate limiting at all. The limit_req_zone key determines the limiting granularity: $binary_remote_addr limits by IP (compact 4–16 bytes), $http_x_api_key limits by API key header, $http_authorization limits by bearer token.

Common mistakes

  • Not specifying limit_req_status 429 — Nginx defaults to returning 503 for rate-limited requests, which is semantically incorrect.
  • Using $remote_addr instead of $binary_remote_addr for the zone key — the binary form uses 4 bytes per IPv4 address instead of 15, allowing ~2.5× more entries in the same memory zone.
  • Not adding a Retry-After header — the rate-limited client has no signal for when to retry.