← Recipes

阅读中文版本

Add Nginx Rate Limiting Near the Edge

Define a shared memory zone, apply a limit_req with burst and nodelay, and return 429 so abusive clients are slowed before they reach the application.

~30 minnginxrate-limitingreliability

Task

Protect backends by rate limiting requests at the Nginx layer.

When to use this

A burst of traffic from one client reaches the application, exhausting workers, while there is no cheap edge control to slow it.

Prerequisites

  • Nginx with http limit_req module
  • A key that identifies the client

Steps

1. Define a limit_req_zone keyed by a suitable client identifier.

Expected output: Requests are counted per key in shared memory.

2. Apply limit_req with a burst allowance and the nodelay option.

Expected output: Short bursts are tolerated but sustained abuse is limited.

3. Return 429 with a Retry-After header when the limit is exceeded.

Expected output: Clients can back off.

4. Choose the key carefully: prefer an API key over the raw remote address behind a proxy.

curl -s -o /dev/null -w "%{http_code}\n" https://app.example.com/ -H "X-Api-Key: $KEY"

Expected output: Shared NAT users are not all throttled.

Troubleshooting

Problem

All users behind one NAT throttled

Solution

Key by API key or authenticated user, and configure real_ip so the address reflects the client.

Problem

Bursts still hit the app

Solution

Reduce burst, or place the limit on the specific expensive location rather than globally.

Limitations

  • Nginx rate limiting is per-instance unless the zone is shared and consistent across nodes.
  • A naive remote-address key misbehaves behind proxies and shared NAT, throttling the wrong clients.

Context

Protect backends by rate limiting requests at the Nginx layer. A burst of traffic from one client reaches the application, exhausting workers, while there is no cheap edge control to slow it.

Steps

  1. Define a limit_req_zone keyed by a suitable client identifier. Expected: Requests are counted per key in shared memory.
  2. Apply limit_req with a burst allowance and the nodelay option. Expected: Short bursts are tolerated but sustained abuse is limited.
  3. Return 429 with a Retry-After header when the limit is exceeded. Expected: Clients can back off.
  4. Choose the key carefully: prefer an API key over the raw remote address behind a proxy. Expected: Shared NAT users are not all throttled.
limit_req_zone $http_x_api_key zone=api:10m rate=20r/s;
server {
  location /api/ {
    limit_req zone=api burst=40 nodelay;
    limit_req_status 429;
    proxy_pass http://app;
  }
}

Verify

  • Requests are counted per key in shared memory.
  • Short bursts are tolerated but sustained abuse is limited.
  • Clients can back off.
  • Shared NAT users are not all throttled.

Limits

  • Nginx rate limiting is per-instance unless the zone is shared and consistent across nodes.
  • A naive remote-address key misbehaves behind proxies and shared NAT, throttling the wrong clients.