Design an API Rate Limiter, stage 8 of 10: change it
Credential stuffing on login
Login is unauthenticated, so there is no API key. The traffic is not one heavy client; it is thousands of light ones.
System so far· 5 parts
Select a component to see what it is responsible for and which state it owns.
- 1API clients → Load balancer: Requests with API key
- 2Load balancer → API instances: Round-robin across instances
- 3API instances → Redis: Atomic take-tokens script
- 4API instances → Postgres: Admitted requests; plan lookups (cached)
What you need to know
Credential stuffing tests leaked email–password pairs from other sites against your login page. Attackers spread the attempts over thousands of IPs, often residential proxies, so each IP makes only a few attempts an hour.
A rate limit catches abuse that is concentrated in the key it counts by. Distributed attacks are built to stay under every per-key limit.
Work it out
8,000 IPs each try 4 passwords an hour. About how many login attempts is that per day?So login protection counts by several keys at once:
Key Catches Per IP one machine hammering Per account many guesses at one user's password Per IP + account one source retrying one user Global failure rate a distributed attack, visible only in aggregate And the response can escalate (add a delay, require a CAPTCHA) instead of hard-blocking.
Think first
You lock any account for an hour after 5 failed logins. What can an attacker who only knows a victim's email address do?