Multiple matching limit_req

Francis Daly francis at
Fri Jan 9 19:16:08 UTC 2015

On Fri, Jan 09, 2015 at 07:18:37PM +0530, Joyce Babu wrote:

Hi there,

> I would like to apply rate limiting based on 3 different criteria.
> 1. CDN should have rate limit of 100 r/s (identified by $http_host)
> 2. Whitelisted bots should have a rate limit of 15 r/s (identified by
> $http_user_agent)
> 3. All other users should have a rate limit of 5 r/s
> The rules should be applied in the above order of preference. If a rule
> matches two criteria, the earlier one should get applied. How can I ensure
> this?

You can't.

All limits that match are applied, which means that the most restrictive
one is seen.

What you *can* do is change your specification with that in mind, and
choose your keys so that they are empty when you do not want the limit
to apply.

> map $http_host $limit_cdn {
>     default '';
>     "" $binary_remote_addr;
> }
> map $http_user_agent $limit_bot {
>     default '';
>     ~*(google|bing) $binary_remote_addr;
> }

Add the following variables with names that more closely resemble what they
are intended to do:

map $limit_cdn $limit_bot_not_cdn {
   default '';
   '' $limit_bot;

map $limit_cdn$limit_bot $limit_not_bot_not_cdn {
   '' $binary_remote_addr;
   default '';

And use those variables as the keys that you actually mean:

> limit_req_zone $limit_cdn zone=limit_cdn:1m rate=100r/s;

Leave that one as-is.

> limit_req_zone $limit_bot zone=limit_bot:1m rate=15r/s;

Change that to be

  limit_req_zone $limit_bot_not_cdn zone=limit_bot:1m rate=15r/s;

> limit_req_zone $binary_remote_addr zone=limit_all:10m rate=5r/s;

Change that to be

  limit_req_zone $limit_not_bot_not_cdn zone=limit_all:10m rate=5r/s;

> limit_req zone=limit_all burst=12;
> limit_req zone=limit_bot burst=50 nodelay;
> limit_req zone=limit_cdn burst=200 nodelay;

and the rest should work as you want.

(Unless you use "return".)

Francis Daly        francis at

More information about the nginx mailing list