5

Using nginx rate limiting, using this rule as an example:

limit_req_zone $request_limiting_zone_key zone=request_limiting_search:20m rate=30r/m;

This will set 30 requests per minute. However what if I wanted to stack a second rule, so the logic is "30 requests per minute, or 1 request per second. Whichever comes first"

The reason for this is we still want a cap of 30/min but there are some weird attempts that we're seeing a spam of 10x requests in a 1-2 second period. This causes some issues when requests come through that fast. So we would like to limit users to 1 request a second, AND a cap of 30 per minute.

I read the doc reference but didn't see much around stacking different rate rules.

Is this possible? If so, what would be the syntax?

1
  • I don't need multiple zones. I need multiple rules on the same zone.
    – emmdee
    Jul 25, 2019 at 1:20

1 Answer 1

4

It is perfectly valid to apply multiple zones to the same block. You may also create multiple zones that store requests for the very same key (typically some prefix of client IP address). It only costs minimal processing and memory.

The following will limit users, identified by their network address, both in second and minute intervals - and allow them to temporarily exceed the defined limit for short bursts. You want to allow that, as it will make your website appear less broken for user with unreliable input devices and/or network access - they might issue the same request twice:

map $remote_addr $request_limiting_zone_key {
    # [..]
}
limit_req_zone $request_limiting_zone_key zone=request_limit_search_second:10m rate=1r/s;
limit_req_zone $request_limiting_zone_key zone=request_limit_search_minute:10m rate=30r/m;

 # [..]

location /search {
    limit_req zone=request_limit_search_second burst=3;
    limit_req zone=request_limit_search_minute burst=3;
}

That being said, if your web server cannot handle a short burst of search requests, maybe you are going to need to offload your search engine to some other machine or apply a different kind of rate limit. You need a significant margin between typical human usage and usage which exceeds your machines ability to keep up. Otherwise you might not find a safe value between annoying legitimate users and failing to restrict abusive/bot usage.

3
  • Oops, missed a crucial part: Without burst and/or nodelay, doing this is entirely pointless - the lower rate limitation would always trigger first.
    – anx
    Jul 25, 2019 at 3:24
  • Appreciate the concise direct answer + example + extra details making it a well rounded solution to the question. Also, no worries on the annoying legit users as th limits imposed are way outside a normal human-use scenario as we're getting several results per second and no bot should be traversing /search... (it's denied in robots). Again, appreciate the input and information.
    – emmdee
    Jul 25, 2019 at 3:43
  • If we add burst, "minutes" rule still has lower rate and still wins, doesn't it? "Seconds" rule accepts up to 3 requests per second (1 request in 333 ms) while "minutes" rule accepts up to 3 requests per 2 seconds (1 request in 666 ms). If both rules should allow request so that nginx accepts it, then "minutes" rule will always have priority, doesn't it?
    – andreycha
    Sep 27, 2023 at 12:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .