# How do I build smart rate limiting against distributed brute force and DDoS?

> Per-IP limits lose to rotating proxies, so key the Redis sliding-window on account + IP + ASN, add account lockout and leave volumetric floods to the edge.

- Asked: 2026-05-29
- Answered: 2026-06-01
- Asked by: Murat
- Tags: dayaniklilik, guvenlik, redis
- Source: https://www.muhammetsafak.com.tr/en/just-ask/smart-rate-limiting-against-distributed-brute-force-and-ddos/
- Language: en-US
- Author: Muhammet Şafak

---
**Question:** Our API's login endpoint is under heavy brute force and DDoS. Standard IP-based rate limiting (60 requests/min) doesn't help because the attacker uses thousands of different IPs behind proxies.

Using a Redis-backed sliding window counter or token bucket, how do I build a dynamic, smart rate limiter that combines IP, username, User-Agent and country code?


Short answer: a per-IP limit is helpless against rotating proxies — so don't dimension only on IP. Break the attack with multi-dimensional keying and defense in depth.

The real problem is this: because the attacker rotates thousands of IPs, the "60 per IP" rule never trips for any individual IP. You need to catch the common denominator of the attack.

1. **Key the Redis sliding-window on multiple dimensions.** Token bucket would solve this too — I prefer sliding-window because it's easier to combine dimensions in one structure. Not a single counter, but counters across several dimensions: username (if one account is being sprayed), IP, IP subnet / ASN, User-Agent fingerprint, country code. Even if one IP looks clean, traffic hitting the same `username` from thousands of IPs blows up on that dimension.
2. **Tighten dynamically when the failure rate spikes.** Keep limits loose normally, then automatically narrow them when the error (failed-login) rate jumps. Use a threshold that hardens on the attack signal, not a fixed one.
3. **Add account lockout and a challenge against credential stuffing.** Apply progressive per-account delay/lockout on failed logins; after N attempts require a CAPTCHA or proof-of-work. This separately closes the single-target version of the distributed attack (account takeover).
4. **Push true volumetric DDoS to the edge.** Your app can't absorb an L3/L7 flood — accept that. Leave the volumetric attack to an edge layer like Cloudflare; your Redis limiter stops smart, targeted abuse, but a flood needs the infrastructure layer.
5. **Fail closed on the login path, and don't leak which dimension tripped.** If the limiter or Redis errors, close the login (fail-closed), don't leave it open. When you reject, don't tell the attacker which dimension blew up (e.g. "your IP is blocked"); log the decisions, but only for your own tuning.

**Bottom line:** I'd set up a sliding-window in Redis on `account + IP + ASN`, add account lockout for credential stuffing, and leave the volumetric part to the edge. A single dimension (IP) is never enough; the combination that catches the common denominator of the attack is what solves it.

## Related Reading

- [My non-root container can't write to the mounted storage directory—how do I fix the permissions?](https://www.muhammetsafak.com.tr/en/just-ask/my-non-root-container-cant-write-to-the-mounted-storage-directory/) — Just Ask
- [How do I design a self-healing deploy that auto-rolls back when the error rate spikes?](https://www.muhammetsafak.com.tr/en/just-ask/automated-rollback-on-error-spikes-self-healing-deploys/) — Just Ask
- [Canary or Blue-Green deployment for a fintech API?](https://www.muhammetsafak.com.tr/en/just-ask/canary-vs-blue-green-deployment-for-a-fintech-api/) — Just Ask
