Mastering Nginx Rate Limiting: From Basics to Advanced Configurations
This article explains Nginx's rate‑limiting feature, covering the leaky‑bucket algorithm, basic and advanced directives like limit_req_zone, limit_req, burst, nodelay, whitelist handling, logging, and custom error codes to control request flow and protect services.
How Nginx Limits Traffic
Rate limiting (rate‑limiting) in Nginx is a practical feature often misunderstood or misconfigured; it restricts the number of HTTP requests a user can make within a given time frame, whether a simple GET for a homepage or a POST to a login form.
It can serve security purposes, such as slowing brute‑force password attacks, and can help mitigate DDoS attacks by limiting request rates to typical user values while logging target URLs. More commonly, it protects upstream application servers from being overwhelmed by too many simultaneous requests.
This article introduces the fundamentals and advanced configurations of Nginx rate limiting, applicable to both Nginx and Nginx Plus.
Underlying Algorithm
Nginx uses the leaky‑bucket algorithm, widely employed in networking to handle burst traffic when bandwidth is limited. Imagine a bucket that leaks water at a constant rate while water is poured in; excess water overflows, analogous to excess client requests being discarded.
Basic Rate‑Limiting Configuration
The two main directives are limit_req_zone and limit_req:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;</code>
<code>server {</code>
<code> location /login/ {</code>
<code> limit_req zone=mylimit;</code>
<code> proxy_pass http://my_upstream;</code>
<code> }</code>
<code>} limit_req_zonedefines the shared memory zone and parameters (key, zone size, rate). limit_req enables the limit in a specific context, such as a location block.
Key – identifies the request attribute used for limiting (e.g., $binary_remote_addr).
Zone – shared memory area storing per‑IP state; size determines how many IPs can be tracked.
Rate – maximum request rate (e.g., 10 requests per second, which Nginx tracks in 100 ms intervals).
If Nginx runs out of space for new entries, it removes old ones; if still insufficient, it returns a 503 status. To prevent memory exhaustion, Nginx deletes up to two unused entries per 60 seconds when creating a new entry.
Applying limit_req to a location enforces the defined rate, e.g., limiting each IP to 10 requests per second for /login/.
Handling Bursts
When more requests arrive than the configured rate, Nginx can buffer excess requests using the burst parameter:
location /login/ {</code>
<code> limit_req zone=mylimit burst=20;</code>
<code> proxy_pass http://my_upstream;</code>
<code>} burstdefines how many requests exceeding the rate can be queued (e.g., 20). Requests beyond the burst limit receive a 503 response.
Zero‑Delay Queuing
Adding nodelay makes queued requests processed immediately without additional delay, preventing the site from appearing slow:
location /login/ {</code>
<code> limit_req zone=mylimit burst=20 nodelay;</code>
<code> proxy_pass http://my_upstream;</code>
<code>}With nodelay, requests that arrive “too early” are forwarded instantly if a queue slot is available, while the slot remains occupied for the configured interval (e.g., 100 ms).
Advanced Example: Whitelisting
Combine geo and map to exempt certain IP ranges from rate limiting:
geo $limit {</code>
<code> default 1;</code>
<code> 10.0.0.0/8 0;</code>
<code> 192.168.0.0/64 0;</code>
<code>}</code>
<code>map $limit $limit_key {</code>
<code> 0 "";</code>
<code> 1 $binary_remote_addr;</code>
<code>}</code>
<code>limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;</code>
<code>server {</code>
<code> location / {</code>
<code> limit_req zone=req_zone burst=10 nodelay;</code>
<code> # ...</code>
<code> }</code>
<code>}IPs in the whitelist receive an empty key, bypassing the limit; all other IPs are limited to 5 requests per second.
Multiple limit_req Directives in One Location
When several limit_req directives apply, the strictest limit wins. Example extending the whitelist configuration:
http {</code>
<code> limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;</code>
<code> limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;</code>
<code> server {</code>
<code> location / {</code>
<code> limit_req zone=req_zone burst=10 nodelay;</code>
<code> limit_req zone=req_zone_wl burst=20 nodelay;</code>
<code> }</code>
<code> }</code>
<code>}Whitelisted IPs are limited to 15 r/s, others to the stricter 5 r/s.
Logging
By default, Nginx logs limited requests at the error level:
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"Fields include limiting status, excess count, zone, client IP, server, request line, and host. The log level can be changed with limit_req_log_level, e.g., to warn:
location /login/ {</code>
<code> limit_req zone=mylimit burst=20 nodelay;</code>
<code> limit_req_log_level warn;</code>
<code> proxy_pass http://my_upstream;</code>
<code>}Custom Error Codes
By default, exceeded limits return HTTP 503. Use limit_req_status to return a different code, such as 444:
location /login/ {</code>
<code> limit_req zone=mylimit burst=20 nodelay;</code>
<code> limit_req_status 444;</code>
<code>}Deny All Requests for a Specific Location
location /foo.php {</code>
<code> deny all;</code>
<code>}Summary
The article covered Nginx and Nginx Plus rate‑limiting features, including per‑location request rates, burst and nodelay parameters, whitelist/blacklist configurations, and logging of delayed or rejected requests.
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
