Rate Limiting at the Reverse Proxy: Our Nginx Config
1 min read
Before
We were using a Go middleware that checked a Redis counter on every request. Works fine, but:
- Each request pays a ~2ms Redis round-trip
- The middleware added complexity to every route handler
- Restarting the app reset in-memory counters
After: Nginx rate limiting
# Define a shared memory zone for rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
# Apply to the API upstream
server {
location /api/ {
limit_req zone=api burst=200 nodelay;
proxy_pass http://backend;
}
}
What changed
- Zero application code changes
- Rate limiting survives app restarts (Nginx owns the state)
- Burst handling is built-in — the
burst=200 nodelaysoaks up spikes - The zone uses 10MB of shared memory, good for ~160k unique IPs
What I learned
Move cross-cutting concerns to the edge when you can. Rate limiting, TLS termination, gzip, and static file serving are all things Nginx does better than your app. Your application code should handle business logic, not infrastructure.