Why limit request rate in Nginx
The limit_req and limit_conn modules protect a server from overload: from bots that brute-force forms, from scrapers that crawl a catalog, and from a plain traffic spike after a marketing email. Without limits, a single client can occupy every PHP-FPM worker and take the site down for everyone else.
limit_req restricts the request rate per second from a single IP address. limit_conn restricts the number of simultaneous connections. These are different mechanisms, and they are often used together.
How to configure limit_req
The memory zone for a limit is declared once in the http {} section, and applied inside the needed location:
http {
limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s;
}
server {
location /login.php {
limit_req zone=perip burst=10 nodelay;
}
}The perip zone sized at 10 MB stores roughly 160 thousand unique IP addresses. The rate=5r/s parameter means 5 requests per second from one address on average.
limit_req parameters: what they mean
| Parameter | Value | Effect |
|---|---|---|
| rate | 5r/s, 10r/m | Average request rate from one address |
| burst | number of requests | How many requests above rate to queue |
| nodelay | flag | Do not delay requests from burst, pass them through immediately |
| limit_req_status | response code | Which code to return when exceeded, 503 by default |
Without nodelay, Nginx holds back extra requests and serves them with a delay, smoothing the flow. With nodelay, requests from burst are processed right away, and extra ones are dropped with code 503.
How to configure limit_conn
limit_conn restricts the number of simultaneous connections from one address — useful against downloading large files in several threads or against slow bots:
http {
limit_conn_zone $binary_remote_addr zone=connperip:10m;
}
server {
location /download/ {
limit_conn connperip 3;
}
}This setting allows no more than three simultaneous connections from one IP address to the /download/ directory.
How to return a clear error code
By default Nginx returns code 503 Service Unavailable when a limit is exceeded. For an API, code 429 Too Many Requests is more logical:
limit_req_status 429;
limit_conn_status 429;Additionally configure a custom error page with error_page 429 /rate-limit.html;, so a visitor sees a clear message instead of a bare response code.
Where to apply limits, and where not to
It makes sense to limit specific addresses, not the whole site:
- login and registration forms — against password brute-forcing
- site search — against scrapers that load the database
- the API — against clients that send requests faster than agreed
- static assets and the homepage are better left alone: limits there hurt more often than they help
Summary
A checklist for rolling out limits:
- declare the limit_req_zone and limit_conn_zone memory zones in http {}
- apply the limit selectively — to login forms, search, and the API
- tune rate and burst to real traffic, not by guessing
- return code 429 instead of 503 where the limit protects an API
Limits are worth combining with overall server protection: see the article on general Nginx security hardening and on diagnosing 502 and 504 errors, which often come from backend overload rather than from Nginx itself.