Introduction
Many APIs implement rate limiting based on the client IP address to prevent abuse. However, when multiple legitimate users share the same outbound IP -- such as behind a corporate NAT, mobile carrier CGNAT, or public proxy -- they share the rate limit quota. One active user can consume the entire quota, blocking all other users behind the same IP.
Symptoms
- Users behind corporate networks receive
429 Too Many Requestsunexpectedly - Rate limit errors correlate with shared IP ranges (corporate offices, ISPs)
- Individual users within the same organization cannot all use the API simultaneously
X-RateLimit-Remainingshows zero despite the individual user making few requests- Error message:
{"error":"rate_limited","message":"Too many requests from this IP"}
Common Causes
- Rate limiter using only the source IP without considering authentication
- Corporate NAT gateway sharing one public IP across hundreds of employees
- Mobile carrier CGNAT putting thousands of users behind the same IP
- API lacking support for API key-based rate limiting as an alternative
- Rate limit threshold set too low for shared IP scenarios
Step-by-Step Fix
- 1.Identify the rate limiting mechanism: Check how the API limits requests.
- 2.```bash
- 3.# Check rate limit headers in API responses
- 4.curl -s -I https://api.example.com/data | grep -i "rate"
- 5.# Look for:
- 6.# X-RateLimit-Limit: 100
- 7.# X-RateLimit-Remaining: 0
- 8.# X-RateLimit-Reset: 1712649600
- 9.
` - 10.Implement API key-based rate limiting: Use authenticated identity instead of IP.
- 11.```python
- 12.# API gateway rate limiting configuration
- 13.# Use API key or user ID as the rate limit key instead of IP
- 14.rate_limit:
- 15.key: "api_key" # Instead of "client_ip"
- 16.requests_per_minute: 100
- 17.per_user: true
- 18.
` - 19.Add X-Forwarded-For header awareness: Detect real client IPs behind proxies.
- 20.```nginx
- 21.# Nginx rate limiting with real IP
- 22.set_real_ip_from 10.0.0.0/8;
- 23.real_ip_header X-Forwarded-For;
- 24.real_ip_recursive on;
- 25.limit_req_zone $realip_remote_addr zone=api:10m rate=10r/s;
- 26.
` - 27.Implement graduated rate limits: Different limits for authenticated vs. anonymous users.
- 28.```yaml
- 29.rate_limits:
- 30.anonymous:
- 31.by: ip
- 32.requests_per_minute: 20
- 33.authenticated:
- 34.by: api_key
- 35.requests_per_minute: 200
- 36.enterprise:
- 37.by: api_key
- 38.requests_per_minute: 1000
- 39.
` - 40.Add rate limit exemption for known shared IP ranges: Whitelist corporate networks.
- 41.```yaml
- 42.rate_limit_exemptions:
- 43.- cidr: "203.0.113.0/24" # Known corporate network
- 44.limit: 1000 # Higher limit for shared IPs
- 45.key_by: api_key
- 46.
`
Prevention
- Use authenticated identity (API key, user ID) as the primary rate limit key
- Implement IP-based rate limiting only as a fallback for unauthenticated requests
- Monitor rate limit hits by IP range to identify shared IP scenarios
- Set higher rate limits for authenticated users compared to anonymous ones
- Provide enterprise customers with dedicated rate limit tiers
- Implement sliding window rate limiting instead of fixed windows to prevent burst blocking