- Public read-only endpoints can tolerate very high throughput (e.g., ~10,000 req/min).
- Resource-creation endpoints consume more compute and should be throttled tighter (e.g., ~100 req/min).
- Authentication endpoints must be the strictest to prevent credential-stuffing attacks.
- Endpoint path or route pattern
- HTTP method
- User role or subscription tier
- API key or client identifier
Question 2 — One Redis isn’t enough at high scale
A single Redis instance often cannot handle extreme loads. For example, a single instance might handle on the order of ~100k ops/sec (varies by instance type and command mix). At 1M req/sec you’ll need to shard across multiple Redis instances — roughly 10 shards in a simplified estimate.
Rate-limiting is naturally partitionable by principal: Alan’s bucket is independent of John’s bucket. Use sharding keyed by principal (user ID, API key, client ID) so every request for the same principal routes to the same Redis shard. This preserves correctness without cross-shard coordination.

- Fast local rejection: once the gateway determines a principal is blocked locally, it can reject further requests without hitting Redis.
- Reduced Redis load: batching reduces the number of Redis operations significantly.
- Slightly relaxed global enforcement during the sync window: multiple gateways may accept requests before their local counters are flushed to Redis. Choose the sync interval based on the acceptable error bound vs. performance.
- Need to manage edge cases: gateway restarts or crashes can lose the in-memory counters unless you use a short sync interval or persist counters on exit.
Using local counters with periodic synchronization is a practical optimization: it reduces Redis load and improves latency while introducing a small, bounded inaccuracy in enforcement. Tune the sync interval to balance performance and strictness.
- Early local deny lists: after a gateway locally observes sustained abusive behavior, add the principal to an in-memory deny list and apply a cooldown before re-evaluating in Redis.
- Backoff and rate-limited error responses: instruct clients to back off (e.g.,
Retry-After) to reduce repeated hits. - Edge filtering: push basic throttling logic as close to the client as possible (CDN, WAF, or edge proxies) to filter obvious abuse before it reaches gateways.
- Redis official documentation: https://redis.io/
- Rate limiting patterns: https://en.wikipedia.org/wiki/Rate_limiting
- Consistent hashing for sharding: https://en.wikipedia.org/wiki/Consistent_hashing
- Use configurable rules per endpoint/principal rather than a single global limit.
- Shard Redis and route by principal to scale to high request rates while keeping correctness.
- Employ local gateway counters with periodic sync to avoid a Redis call on every request, trading a small accuracy window for large performance gains.
- Combine local optimizations with defensive measures (deny lists, backoff headers, edge filtering) to reduce wasted work from abusive clients.