HxHippy

Rate Limiting

Protecting your server from abuse with Nginx rate limiting.

Last updated: 2025-01-15

Basic Rate Limiting

# Define rate limit zone (in http context)
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;

server {
    location / {
        # Apply rate limit
        limit_req zone=general burst=20 nodelay;
        # ...
    }
}

Zone Parameters

# Format: limit_req_zone key zone=name:size rate=rate;

# Per IP address (most common)
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;

# Per server name
limit_req_zone $server_name zone=perserver:10m rate=100r/s;

# Per URI
limit_req_zone $request_uri zone=peruri:10m rate=5r/s;

# Combination
limit_req_zone $binary_remote_addr$request_uri zone=combo:10m rate=1r/s;

Burst Handling

# No burst (strict)
limit_req zone=general;

# With burst queue (requests wait)
limit_req zone=general burst=20;

# With burst, no delay (excess allowed immediately)
limit_req zone=general burst=20 nodelay;

# Two-stage rate limiting
limit_req zone=general burst=20 delay=10;
# First 10 requests: no delay
# Next 10 requests: delayed
# After 20: rejected

Different Limits for Different Endpoints

# Strict limit for login
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

# Normal limit for API
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

# Generous limit for static files
limit_req_zone $binary_remote_addr zone=static:10m rate=100r/s;

server {
    location /login {
        limit_req zone=login burst=3 nodelay;
        # ...
    }

    location /api/ {
        limit_req zone=api burst=20;
        # ...
    }

    location /static/ {
        limit_req zone=static burst=50 nodelay;
        # ...
    }
}

Connection Limiting

# Limit concurrent connections per IP
limit_conn_zone $binary_remote_addr zone=connperip:10m;

server {
    # Max 10 connections per IP
    limit_conn connperip 10;

    # Limit connection rate to downstream
    limit_rate 100k;  # 100KB/s per connection
}

Custom Error Responses

# Custom 429 response
limit_req_status 429;

error_page 429 /429.html;
location = /429.html {
    root /var/www/html;
    internal;
}

# Or return JSON for API
location /api/ {
    limit_req zone=api burst=10;

    error_page 429 = @rate_limited;
}

location @rate_limited {
    default_type application/json;
    return 429 '{"error": "Too Many Requests", "retry_after": 60}';
}

Logging

# Log rate limited requests
limit_req_log_level warn;  # error, warn, notice, info

# Dry run mode (log but don't limit)
limit_req_dry_run on;
intermediate Security Updated 2025-01-15
  • nginx
  • rate limiting
  • throttling
  • ddos
  • security