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 Requests unexpectedly
  • 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-Remaining shows 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. 1.Identify the rate limiting mechanism: Check how the API limits requests.
  2. 2.```bash
  3. 3.# Check rate limit headers in API responses
  4. 4.curl -s -I https://api.example.com/data | grep -i "rate"
  5. 5.# Look for:
  6. 6.# X-RateLimit-Limit: 100
  7. 7.# X-RateLimit-Remaining: 0
  8. 8.# X-RateLimit-Reset: 1712649600
  9. 9.`
  10. 10.Implement API key-based rate limiting: Use authenticated identity instead of IP.
  11. 11.```python
  12. 12.# API gateway rate limiting configuration
  13. 13.# Use API key or user ID as the rate limit key instead of IP
  14. 14.rate_limit:
  15. 15.key: "api_key" # Instead of "client_ip"
  16. 16.requests_per_minute: 100
  17. 17.per_user: true
  18. 18.`
  19. 19.Add X-Forwarded-For header awareness: Detect real client IPs behind proxies.
  20. 20.```nginx
  21. 21.# Nginx rate limiting with real IP
  22. 22.set_real_ip_from 10.0.0.0/8;
  23. 23.real_ip_header X-Forwarded-For;
  24. 24.real_ip_recursive on;
  25. 25.limit_req_zone $realip_remote_addr zone=api:10m rate=10r/s;
  26. 26.`
  27. 27.Implement graduated rate limits: Different limits for authenticated vs. anonymous users.
  28. 28.```yaml
  29. 29.rate_limits:
  30. 30.anonymous:
  31. 31.by: ip
  32. 32.requests_per_minute: 20
  33. 33.authenticated:
  34. 34.by: api_key
  35. 35.requests_per_minute: 200
  36. 36.enterprise:
  37. 37.by: api_key
  38. 38.requests_per_minute: 1000
  39. 39.`
  40. 40.Add rate limit exemption for known shared IP ranges: Whitelist corporate networks.
  41. 41.```yaml
  42. 42.rate_limit_exemptions:
  43. 43.- cidr: "203.0.113.0/24" # Known corporate network
  44. 44.limit: 1000 # Higher limit for shared IPs
  45. 45.key_by: api_key
  46. 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