Skip to content

Rate Limiting

Basic Configuration

bash
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

server {
    location /login/ {
        limit_req zone=mylimit;
        proxy_pass http://my_upstream;
    }
}
  • limit_req_zone: Defines the params for rate limiting.
    • Defined in the http block
  • $binary_remote_addr: Binary format remote address.
    • Limiting each unique IP address to the request rate.
      • Less space than remote_addr(string format).
  • zone:mylimit:10m: Defines a 10 megabyte shared memory.
    • About 16000 IPS per megabyte.
      • If storage is exhausted, it removes the oldest entry.
  • limit_req: Enables rate limiting.
    • Defined in localtion or server block.
  • rate=10r/s: 10 requests per second.
    • NGINX actually tracks requests at millisecond.
      • The actual limit is 1 request per 100 milliseconds (ms).

Handling Bursts

bash
location /login/ {
    limit_req zone=mylimit burst=20;
    proxy_pass http://my_upstream;
}
  • burst=20: Queue size 20, like a buffer.
    • If 22 requests arrive at the same time.
      • 1 request will forward to the backend upstream.
      • 20 requests will go to the buffer.
      • 1 request will return 503 to the client.

Queueing with No Delay

bash
location /login/ {
    limit_req zone=mylimit burst=20 nodelay;
    proxy_pass http://my_upstream;
}
  • nodelay: Forward it immediately if the queue is not full.
    • No queue pop action.
      • Release queue slot after 100ms(rate=10r/s).

Log Level

prolog
2015/06/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone “mylimit”, client: 192.168.1.2, server: nginx.com, request: “GET / HTTP/1.0”, host: “nginx.com”

By default, NGINX logs refused requests at the error level.

bash
location /login/ {
    limit_req zone=mylimit burst=20 nodelay;
    limit_req_log_level warn;
    proxy_pass http://my_upstream;
}

Error Code Sent to Client

bash
location /login/ {
    limit_req zone=mylimit burst=20 nodelay;
    limit_req_status 444;
}

Denying to a Location

bash
location /foo.php {
    deny all;
}

Advanced Configuration

bash
geo $limit {
    default 1;
    10.0.0.0/8 0;
    192.168.0.0/24 0;
}

map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;

}

limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;

server {
    location / {
        limit_req zone=req_zone burst=10 nodelay;
    }
}
  • geo $limit: Set $limit value by client ip.
    • If client ip in range 10.0.0.0/8, set $limit to 0.
      • If client ip in range 192.168.0.0/24, set $limit to 0.
      • Otherwise, set $limit to 1.
  • map $limit $limit_key: Set $limit_key value by $limit.
    • If $limit is 0, set $limit_key to "".
      • If $limit is 1, set $limit_key to $binary_remote_addr.
  • limit_req_zone:
    • If $limit_key is "", let it go.
      • If $limit_key is $binary_remote_addr, check request rate.

Reference