Implementing Rate Limiting
1. Defining Limit Request Zone
| Directive | Values | Description |
|---|---|---|
| limit_req_zone | zone=name:rate |
Defines a shared memory zone to hold the state of requests and the rate at which they are allowed |
| zone | name:size |
Name of the zone and size of shared memory (e.g., zone=one:10m) |
| rate | number |
Rate of requests per second (e.g., rate=1r/s) or per minute (e.g., rate=5r/m) |
Example: Rate limiting with burst
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_req zone=one burst=5 nodelay;
2. Applying Rate Limit
| Directive | Description | Example |
|---|---|---|
| limit_req | Enables rate limiting based on a defined zone | limit_req zone=api_limit burst=10; |
| limit_req_zone | Defines a rate limit zone with a key and rate | limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s; |
| burst | Number of requests allowed to exceed the rate limit before being rejected | limit_req zone=api_limit burst=5; |
| nodelay | Disables delay for burst requests | limit_req zone=api_limit burst=5 nodelay; |
Example: Basic Rate Limit Configuration
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s;
server {
listen 80;
location /api/ {
limit_req zone=api_limit burst=5 nodelay;
proxy_pass http://backend;
}
}
}
Note: The
$binary_remote_addr variable is used to uniquely identify clients.
Warning: Ensure that the zone size is sufficient to handle expected traffic. Zone size is limited to 1MB per 10,000 entries.
3. Setting Burst Parameter
| Directive | Values | Description |
|---|---|---|
| limit_req | burst=5 |
Sets the maximum number of requests allowed to exceed the rate limit before being dropped or delayed |
Example: Configuring Burst Limit
limit_req_zone $binary_remote_addr zone=api:10m rate=1r/s;
server {
location /api/ {
limit_req zone=api burst=5 nodelay;
proxy_pass http://backend;
}
}
Note: The
burst parameter allows temporary bursts of requests to be handled without immediate rejection, improving user experience during short spikes in traffic.
4. Using No Delay Option
| Directive | Description | Values | Notes |
|---|---|---|---|
| limit_req | Enables rate limiting for a given zone | zone=name, burst=number, nodelay |
When nodelay is used, requests are not delayed but immediately rejected if the burst limit is exceeded |
Example: Using nodelay in limit_req
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api nodelay;
proxy_pass http://backend;
}
}
Note: The
nodelay option is useful for APIs where immediate rejection is preferred over queuing requests.
5. Configuring Connection Limit
| Directive | Values | Description |
|---|---|---|
| limit_conn_zone | zone=name:size |
Defines a shared memory zone to store connection state |
| limit_conn | zone=name; burst=number; nodelay |
Applies connection limits to a zone |
Example: Basic Connection Limiting
http {
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_conn_zone $server_name zone=conn_limit_per_server:10m;
server {
listen 80;
server_name example.com;
limit_conn conn_limit_per_ip 10;
limit_conn conn_limit_per_server 100;
}
}
Example: Burst Connection Limiting
http {
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
server {
listen 80;
server_name example.com;
limit_conn conn_limit_per_ip 10;
limit_conn burst=5 nodelay;
}
}
Note: The
limit_conn_zone directive must be placed in the http block, not inside a server block.
Warning: If
limit_conn_zone is not configured properly, the connection limiting will not work as expected.
6. Applying Connection Limit
| Directive | Values | Description |
|---|---|---|
| limit_conn_zone | zone=name:size |
Defines a shared memory zone to store connection state |
| limit_conn | zone=name:connections |
Applies the connection limit to a zone |
Example: Configuring Connection Limits
http {
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
limit_conn_zone $server_name zone=conn_limit_per_server:10m;
server {
listen 80;
server_name example.com;
location / {
limit_conn conn_limit_per_ip 10;
limit_conn conn_limit_per_server 100;
}
}
}
Note: The
limit_conn_zone directive must be defined at the http level, and limit_conn is applied per location or server block.
Key Points
- limit_conn_zone creates a shared memory zone to track connections.
- limit_conn enforces limits on the number of concurrent connections.
- Use
$binary_remote_addrfor IP-based limits or$server_namefor server-specific limits.
7. Setting Rate Limit Status
| Directive | Values | Description |
|---|---|---|
| limit_req_status | 429 |
Status code returned when rate limit is exceeded |
| limit_req_status | 403 |
Alternative status code for rate limit exceeded |
| limit_req_status | 503 |
Service unavailable status for rate limit exceeded |
Example: Configuring 429 Status Code
limit_req_status 429;
server {
listen 80;
server_name example.com;
location /api/ {
limit_req zone=api_req burst=5 nodelay;
proxy_pass http://backend;
}
}
Note: The
limit_req_status directive controls the HTTP status code returned when a client exceeds the rate limit. Common values are 429 (Too Many Requests), 403 (Forbidden), or 503 (Service Unavailable).
8. Logging Rate Limit Events
| Directive | Description | Default |
|---|---|---|
| limit_req_log_level | Sets the logging level for rate limit events | error |
Note: Setting
limit_req_log_level to info or lower will log rate limit events at that level.
| Log Format | Description | Example |
|---|---|---|
| $limit_req_status | Indicates whether the request was limited | limited or allowed |
| $limit_req_key | Key used for rate limiting | 192.168.1.1 |
Example: Custom Log Format
log_format rate_limit "$remote_addr - $limit_req_status [$time_local] "
"Request: $request_uri, Key: $limit_req_key";
access_log /var/log/nginx/rate_limit.log rate_limit;
9. Using Multiple Rate Limits
When implementing rate limiting in Nginx, you can apply multiple limits to different resources or paths. This allows for granular control over traffic and helps prevent abuse.
| Directive | Description | Example |
|---|---|---|
| limit_req | Applies rate limiting to a location or server block. | limit_req zone=api_limit burst=10; |
| limit_req_zone | Defines a shared memory zone for storing rate limit data. | limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s; |
| burst | Number of requests allowed to exceed the rate limit before being delayed or dropped. | limit_req zone=api_limit burst=5; |
| nodelay | Disables delay for burst requests. | limit_req zone=api_limit burst=5 nodelay; |
Example: Applying Multiple Rate Limits
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=static_limit:10m rate=5r/s;
server {
listen 80;
location /api/ {
limit_req zone=api_limit burst=10;
}
location /static/ {
limit_req zone=static_limit burst=20;
}
}
}
Note: Each
limit_req_zone directive defines a unique zone with its own rate and burst settings. These zones can be applied to different locations or paths independently.
10. Excluding IPs from Rate Limiting
| Directive | Description | Example |
|---|---|---|
| limit_req_zone | Defines a shared memory zone for rate limiting | limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; |
| limit_req | Applies rate limiting to a location or server block | limit_req zone=api burst=5 nodelay; |
| limit_req_dry_run | Logs rate limiting without enforcing it | limit_req_dry_run zone=api; |
Example: Exclude Specific IPs from Rate Limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
listen 80;
server_name example.com;
# Exclude specific IPs from rate limiting
location /api/ {
limit_req zone=api burst=5 nodelay;
if ($remote_addr ~ "192.168.1.100|10.0.0.50") {
limit_req off;
}
}
location / {
# Apply rate limiting to all other requests
limit_req zone=api burst=5 nodelay;
}
}
Note: The
if directive is evaluated for each request, so it's best to avoid complex conditions or use map for better performance.
Key Points
- Use
ifwith a regex pattern to match excluded IPs - Set
limit_req off;to disable rate limiting for matching IPs - Place the exclusion logic before applying rate limits in the location block
11. Implementing Dynamic Rate Limits
| Directive | Description | Example |
|---|---|---|
| limit_req | Defines the rate limit for a zone | limit_req zone=api_limit burst=5; |
| limit_req_zone | Defines a rate limit zone with key and rate | limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s; |
| burst | Number of requests allowed to exceed the rate limit before blocking | limit_req zone=api_limit burst=5; |
| nodelay | Do not delay requests, block immediately | limit_req zone=api_limit burst=5 nodelay; |
Example: Dynamic Rate Limiting Configuration
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=api_limit_5s:10m rate=5r/s;
server {
listen 80;
location /api/ {
limit_req zone=api_limit burst=5 nodelay;
proxy_pass http://backend;
}
location /api/fast/ {
limit_req zone=api_limit_5s burst=10 nodelay;
proxy_pass http://backend;
}
}
}
Note: The
$binary_remote_addr variable is used to identify clients uniquely.
Warning: Setting
rate=0r/s disables rate limiting.
12. Using Delay Parameter
| Directive | Values | Description |
|---|---|---|
| limit_req | delay |
Enables rate limiting with a delay for requests exceeding the limit. |
Example: Configuring rate limiting with delay
server {
location /api/ {
limit_req zone=api_zone delay=10s;
proxy_pass http://backend;
}
}
Note: The
delay parameter allows the server to queue requests that exceed the rate limit instead of dropping them immediately.