31

The reason I want to do this is because users develop against our API with JavaScript, and some developers screw up and cause visitors to slam the server with AJAX requests. When this happens, I want to be able to throttle the API requests to perhaps 50 requests per minute, or something to that effect.

Note: (particularly DB intensive resources, so perhaps at a path level, rather than server-wide (e.g. throttle "/json_api/", but not "/static/").

kasperd
  • 29,894
  • 16
  • 72
  • 122
orokusaki
  • 2,693
  • 4
  • 28
  • 42

1 Answers1

39

This can be done using the LimitReqModule with Nginx. However if this is for a reverse proxy you might want to try out the new rate limiting supported by HAProxy.

I found the nginx rate limiting to be a little bit confusing to get the exact rate you want.

But you basically have something like:

limit_req_zone  $binary_remote_addr  zone=default:10m   rate=50r/m;

in the http section and then something like the following in the location section within the server section:

limit_req zone=default burst=10 nodelay;

In order not to have it for a certain section like /static you would just make that a separate location and not include it the limit_req directive (or the inverse).

Kyle Brandt
  • 82,107
  • 71
  • 302
  • 444
  • 1
    thanks. Can you explain what those things are doing (zone, burst, nodelay)? And, did you mean to put `zone=limit_req_zone`, instead? – orokusaki Sep 09 '10 at 19:59
  • Honestly I can't explain them that well which is why I feel it is just to confusing. Michael's explanation in the link I provided sounds like it might be feasible. I don't believe I have any typos as far as your second question goes... The module documentation I linked to has an example that might help. – Kyle Brandt Sep 09 '10 at 20:08
  • 2
    zone, burst and nodelay are documented on [the Nginx wiki page about the rate limiting module](http://wiki.nginx.org/NginxHttpLimitReqModule), linked to already from the answer above. – Mark Stosberg May 25 '12 at 20:13
  • Kyle, do you know if there is a way to combine the rate limit per location with another trigger (e.g. Authorization-Header). In my case I may want to throttle the rate of a specific user. – Nils May 09 '14 at 09:54
  • 1
    @Nils AFAICS you could use the `$http_authorization` variable to define a new zone where the key is such header rather than the IP address, i.e., `limit_req_zone $http_authorization zone = per_user : 10m rate = 5r/s`, and then use the `per_user` zone in the location sections where you want to do the per-user rate limiting. Untested, I only just read the documentation and the list of nginx variables... let me know if you try this out! – nicolagi Nov 03 '14 at 07:46
  • @Nils you can use the map module to map any variable you want. This is used to blacklist / whitelist IPs and it should also be adaptable to your needs. Refer to http://serverfault.com/questions/177461/how-to-rate-limit-in-nginx-but-including-excluding-certain-ip-addresses/642357#642357 – shonky linux user Nov 06 '14 at 01:29