NoCache

Table of Contents

Set Up Rate Limiting with Leaky Bucket Algorithm in Nginx

Cyrus Kao
Last modified on .

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.

Status code 503
A request dropped with status code 503

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 with 3 burst allowed, but every request exceeding 2r/s is delayed and exceeding 3r/s is dropped:

    limit_req zone=general burst=3 delay=2;
    Nginx config
  • No delay

    Apply the general zone with 3 burst allowed, every request exceeding 3r/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

See Also

Comments

Sign in to leave a comment.