Security & SSLrate-limit.conf

How to Configure Rate Limiting in Nginx to Prevent API Abuse & DDoS

Nginx provides an efficient leaky-bucket rate limiting mechanism built directly into C memory buffers. It rejects or queues excessive requests before they ever hit your database or upstream application.

Interactive Nginx Config Generator

rate-limit.conf
/etc/nginx/sites-available/rate-limit.conf
# Define memory zones in the http {} context
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
limit_req_status 429;

server {
    listen 80;
    server_name example.com;

    # General API endpoints: 10 requests/sec with burst of 20
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Strict login rate limit: 5 requests/minute to prevent credential stuffing
    location /api/v1/auth/login {
        limit_req zone=login_limit burst=2 nodelay;
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Directives & Architecture Explained

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

Allocates a 10MB shared memory zone tracking binary client IPs, allowing up to 10 requests per second per IP.

limit_req_status 429;

Instructs Nginx to return HTTP 429 Too Many Requests instead of the default 503 Service Temporarily Unavailable.

burst=20 nodelay;

Allows short bursts up to 20 requests without artificial artificial delay, rejecting the 21st request immediately.

Production Verification & Reload Workflow

sudo nginx -t

Validate limit_req_zone syntax and placement inside http context

ab -n 50 -c 10 http://api.example.com/api/v1/auth/login

Run ApacheBench stress test to confirm excess requests trigger HTTP 429

tail -f /var/log/nginx/error.log | grep limiting

Monitor real-time rate limiting drops in the Nginx error log

Production Troubleshooting Tips

  • β€’If your Nginx sits behind Cloudflare or AWS ALB, $binary_remote_addr will track the proxy IP instead of the visitor! Use $http_cf_connecting_ip or set_real_ip_from directives.
  • β€’Remember limit_req_zone MUST be placed outside server {} blocks in the main http {} block.
  • β€’A 10MB zone can hold state for approximately 160,000 unique concurrent IP addresses.

Frequently Asked Questions

What does nodelay do?

Without nodelay, requests in excess of the rate are delayed with sleep intervals. With nodelay, burst requests execute instantly, and subsequent requests are rejected with 429 immediately.

Why use $binary_remote_addr instead of $remote_addr?

$binary_remote_addr consumes only 4 bytes (IPv4) or 16 bytes (IPv6) in memory, saving 75% RAM compared to ASCII string representations.