Approach overview
I’d implement a hybrid token-bucket + sliding-window counters system: token-bucket for smooth per-IP and per-account throttling, sliding-window for strict bursts and analytics. Add a global emergency throttle that can be toggled automatically from aggregated metrics.
Algorithms
- Per-IP & per-account: token bucket (tokens refilled per minute). On request, atomically consume token; reject when empty.
- Global emergency: aggregated rate across regions; when threshold exceeded, apply progressive backoff (increase cost per request or short global denylist).
- Analytics: sliding-window counters for forensics and anomaly detection.
Storage & consistency
- Fast path: local in-memory token buckets (per node) for latency.
- Shared state: Redis (clustered, primary-replicas) with Lua scripts for atomic token consume when cross-check needed.
- Multi-region convergence: use CRDT-based counters (e.g., PN-Counters) or Redis GCS with periodic reconciliation for global metrics. CRDTs avoid coordination and eventual-consistent summation for emergency decisions.
Cross-region enforcement
- Default: enforce locally using IP/account mapping to the nearest region; periodically sync counts to central ranking via CRDTs.
- Strong enforcement for critical accounts: use a global Redis write (tradeoff: higher latency) or route auth requests through a global rate-check service (cache results).
- Emergency decisions derived from aggregated CRDT counters and a leader-election (fast path) to avoid split-brain.
Avoiding false positives (NAT/proxies)
- Use progressive checks: if many users share IP, prefer per-account limit over per-IP; raise IP threshold if it maps to known carrier NAT ranges.
- Integrate device fingerprinting and TLS client hello entropy to distinguish users.
- Allow higher burst allowance and CAPTCHA/challenge for suspicious sources instead of hard blocking.
- Maintain dynamic allowlists for known CDNs/proxies and apply weighted tokens per sub-IP (X-Forwarded-For parsing when trusted).
Operational considerations
- Use Redis Lua scripts for atomic operations and metrics emission to Kafka for offline analysis.
- Circuit-breakers and graceful degradation: when Redis unavailable, fall back to local token-bucket with conservative limits.
- Metrics/alerts: SLOs for false positives, request rejection rate, and global throttle activations; automated rollback for misconfigurations.
This balances low-latency enforcement, global visibility, and reduced false positives for users behind shared IPs.