Operate and troubleshoot

Control rate and connections

Limit abusive request rates and concurrent work while preserving normal bursts and clear failure behavior.

8 minute lesson

~~~

Nginx can limit request rate per key and concurrent connections per key. This protects expensive endpoints from one aggressive client — a runaway script, a scraper, a brute-force attempt — without touching application code.

Rate limiting takes two directives. In the http context you define a zone; in the location you apply it:

limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

server {
  location /api/ {
    limit_req zone=api burst=20 nodelay;
    limit_req_status 429;
    proxy_pass http://127.0.0.1:3000;
  }
}

The key is $binary_remote_addr, the client IP in compact form, so each address gets its own budget of 10 requests per second. The 10-megabyte zone holds the counters for roughly 160,000 addresses.

The burst is what keeps real users happy. A browser opening a page fires a burst of requests in the same instant — HTML, then a volley of assets and API calls. Without burst, everything past the steady rate in that instant is rejected, and ordinary page loads break. burst=20 allows 20 requests to exceed the rate momentarily, and nodelay serves them immediately instead of queueing them.

limit_req_status 429 makes rejections return 429 Too Many Requests. The default is 503, which monitoring systems read as “server broken” rather than “client throttled” — set 429 so your dashboards stay honest.

Concurrent connections are a separate limit for long-held work like downloads:

limit_conn_zone $binary_remote_addr zone=perip:10m;

location /downloads/ {
  limit_conn perip 5;
}

Test both behaviors separately: normal traffic first, then an intentional excess:

for i in $(seq 1 40); do
  curl -s -o /dev/null -w "%{http_code}\n" https://app.example.com/api/ping
done
# 200 x ~30, then 429 for the rest

The first ~30 requests pass (rate plus burst), then rejections start. Each rejection also writes a limiting requests line to the error log, which is how you’ll spot throttling in production.

Choose a key that represents the client boundary you trust. Behind a CDN or load balancer, $binary_remote_addr is the proxy’s address, so all your users share one bucket and throttle each other — restore the real client IP first, or key on something else. And keep perspective: edge limits complement application authorization and business rules; they do not replace them.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →