Access & rate limiting

Rate-limit requests

3 min read

To stop brute-force and scraping, cap how many requests a client can make. Define a shared zone at http { }, then apply it where it matters.

At http { }:

# 10 requests/second per IP; 10m of state holds ~160k IPs.
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

# Return 429 (Too Many Requests) instead of the default 503.
limit_req_status 429;

In a location (e.g. an API or login):

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

location = /login {
    limit_req zone=req_limit burst=5 nodelay;
    proxy_pass http://127.0.0.1:3000;
}

How it works:

Behind a trusted proxy, recover the real client IP first:

# at http or server level
set_real_ip_from 10.0.0.0/8;       # your load balancer's range
real_ip_header   X-Forwarded-For;
real_ip_recursive on;

Tune burst so normal users (a page that fires several XHRs at once) aren’t hit; logs show limiting requests when it triggers.

sudo nginx -t && sudo nginx -s reload
Open the full version (with copy buttons) ↗

← All snippets