Set Up Rate Limiting with Leaky Bucket Algorithm in Nginx
Nginx came with a rate limit module called ngx_http_limit_req_module
, which is quite handy for throttling harmful requests like DoS attack. And the module uses the leaky bucket algorithm to handle the connections. It could allow a certain amount of burst requests in a short period of time to suit the use cases.
Set Up Rate Limiting
Before setting up rate limiting in Nginx, you'll need a working Nginx server. Refer to this guide for the setup.
Define Zone
First, by defining a limit_req_zone
in http
block, it takes three parameters:
- Key - Identification of the requests. Normally, an IP address in binary format (
$binary_remote_addr
) is used. - Zone
- Name - Name of the zone.
- Size - Size of the storage.
1m
can store 8,000 ~ 16,000 states according to the official documentation.
- Rate - Determined how many requests are allowed in a period of time.
1r/s
means 1 request per second.
Here is a zone named general
with 10m
storage and allows 1r/s
for each $binary_remote_addr
:
http {
limit_req_zone $binary_remote_addr zone=general:10m rate=1r/s;
...
}
Nginx config
Apply to Route
Apply your limit_req_zone
to a route with limit_req
in http
, server
, location
blocks, it takes three parameters as well:
- Zone - Zone name.
- Burst (Optional) - Maximum amount of burst requests allowed before dropping them.
- Delay (Optional) - Maximum amount of burst requests allowed before delaying them.
nodelay
to serve them immediately.
Basic
Apply the general
zone without burst allowed, every request exceeding 1r/s
is dropped:
limit_req zone=general;
Nginx config
With Burst
Apply the general
zone with 3
burst allowed, but every request exceeding 1r/s
is delayed and exceeding 3r/s
is dropped:
limit_req zone=general burst=3;
Nginx config
With Burst and Delay
-
Delay
Apply the
general
zone with3
burst allowed, but every request exceeding2r/s
is delayed and exceeding3r/s
is dropped:limit_req zone=general burst=3 delay=2;
Nginx config -
No delay
Apply the
general
zone with3
burst allowed, every request exceeding3r/s
is dropped:limit_req zone=general burst=3 nodelay;
Nginx config
Set Status Code
By default, every request exceeding the rate limit will be closed with status code 503
, which indicates Service Unavailable
.
If this is not desired, you can change it to something like 429
(Too Many Requests
) with limit_req_status
in http
, server
, location
blocks:
limit_req_status 429;
Nginx config
Full Example
Here is a full example demonstrating the use of multiple limit_req_zone
:
http {
limit_req_zone $binary_remote_addr zone=general:10m rate=6r/s;
limit_req_zone $binary_remote_addr zone=static:1m rate=2r/s;
limit_req_zone $binary_remote_addr zone=api:1m rate=1r/s;
limit_req_status 503; # redundant, since it's default
limit_req zone=general burst=12 delay=9;
server {
...
location /static/ {
limit_req zone=static burst=4 nodelay;
root /static;
}
location /api/ {
limit_req_status 429;
limit_req zone=api;
proxy_pass http://127.0.0.1:3000;
}
}
}
Nginx config