Add Nginx Rate Limiting Near the Edge
Define a shared memory zone, apply a limit_req with burst and nodelay, and return 429 so abusive clients are slowed before they reach the application.
Task
Protect backends by rate limiting requests at the Nginx layer.
When to use this
A burst of traffic from one client reaches the application, exhausting workers, while there is no cheap edge control to slow it.
Prerequisites
- Nginx with http limit_req module
- A key that identifies the client
Steps
1. Define a limit_req_zone keyed by a suitable client identifier.
Expected output: Requests are counted per key in shared memory.
2. Apply limit_req with a burst allowance and the nodelay option.
Expected output: Short bursts are tolerated but sustained abuse is limited.
3. Return 429 with a Retry-After header when the limit is exceeded.
Expected output: Clients can back off.
4. Choose the key carefully: prefer an API key over the raw remote address behind a proxy.
curl -s -o /dev/null -w "%{http_code}\n" https://app.example.com/ -H "X-Api-Key: $KEY"Expected output: Shared NAT users are not all throttled.
Troubleshooting
Problem
All users behind one NAT throttled
Solution
Key by API key or authenticated user, and configure real_ip so the address reflects the client.
Problem
Bursts still hit the app
Solution
Reduce burst, or place the limit on the specific expensive location rather than globally.
Limitations
- Nginx rate limiting is per-instance unless the zone is shared and consistent across nodes.
- A naive remote-address key misbehaves behind proxies and shared NAT, throttling the wrong clients.
Context
Protect backends by rate limiting requests at the Nginx layer. A burst of traffic from one client reaches the application, exhausting workers, while there is no cheap edge control to slow it.
Steps
- Define a limit_req_zone keyed by a suitable client identifier. Expected: Requests are counted per key in shared memory.
- Apply limit_req with a burst allowance and the nodelay option. Expected: Short bursts are tolerated but sustained abuse is limited.
- Return 429 with a Retry-After header when the limit is exceeded. Expected: Clients can back off.
- Choose the key carefully: prefer an API key over the raw remote address behind a proxy. Expected: Shared NAT users are not all throttled.
limit_req_zone $http_x_api_key zone=api:10m rate=20r/s;
server {
location /api/ {
limit_req zone=api burst=40 nodelay;
limit_req_status 429;
proxy_pass http://app;
}
}
Verify
- Requests are counted per key in shared memory.
- Short bursts are tolerated but sustained abuse is limited.
- Clients can back off.
- Shared NAT users are not all throttled.
Limits
- Nginx rate limiting is per-instance unless the zone is shared and consistent across nodes.
- A naive remote-address key misbehaves behind proxies and shared NAT, throttling the wrong clients.