How to Configure an Nginx Rate Limit
Nginx rate limiting uses two directives: limit_req_zone defines the limit, limit_req applies it. Get the rate or burst wrong and you'll 503 legitimate users. Here's how to set it correctly.
The two directives
Nginx rate limiting is a leaky-bucket built from a pair:
# http {} - define a zone: key = client IP, rate = allowed average
limit_req_zone $binary_remote_addr zone=api:10m rate=50r/s;
server {
location /api/ {
# location {} - apply the zone, with a burst buffer
limit_req zone=api burst=50 nodelay;
proxy_pass http://backend;
}
}
rateis the steady allowed rate (50r/s, orr/mfor per-minute).zone=api:10mallocates shared memory to track clients (~160k IPs per 10m).$binary_remote_addrkeys the limit per client IP.
burst + nodelay (the part everyone gets wrong)
Without a burst, nginx rejects the instant a client exceeds the exact rate - even a
normal page that fires a few requests at once gets 503. burst is a queue of extra
requests allowed temporarily:
burst=50- allow up to 50 queued over-rate requests.nodelay- serve those burst requests immediately instead of drip-feeding them.
burst=50 nodelay is the usual "feels normal to users, still capped" setting.
The classic failure: a too-tight limit 503s everyone
A config like rate=1r/m (one request per minute) with no burst will 503 almost all
real traffic - the backend looks healthy because nginx is rejecting requests before they
reach it. The fix is a realistic rate plus a burst:
limit_req_zone $binary_remote_addr zone=api:10m rate=50r/s; # was 1r/m
limit_req zone=api burst=50 nodelay; # was no burst
Reloading the limit
After changing the rate, a full restart is safer than nginx -s reload - reload keeps the
shared-memory zone's in-flight counters, which can keep rejecting requests right after the
change. Validate then restart:
nginx -t && nginx -s stop && nginx
Return 429 instead of 503 for rejections with limit_req_status 429; - it's the
correct "too many requests" code and clients handle it better.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Setting rate + zone with limit_req_zone
- Tuning burst + nodelay so real traffic isn't 503'd
- Restarting nginx so the limit zone resets cleanly
FAQ
How do I rate limit in nginx?
Define a zone with limit_req_zone $binary_remote_addr zone=api:10m rate=50r/s; in the http block, then apply it in a location with limit_req zone=api burst=50 nodelay;.
Why is nginx returning 503 after I added a rate limit?
The limit is too tight or has no burst, so normal traffic exceeds it and nginx rejects requests before they reach the backend. Raise the rate and add burst=... nodelay.
What do burst and nodelay do in limit_req?
burst allows a queue of extra requests above the steady rate (so a normal page firing several requests isn't blocked); nodelay serves those queued requests immediately instead of spacing them out.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →