Why Rate Limiting Is the First Line of Authentication Defense
Stand up a new login page and the probes start within seconds: credentials from breaches, stealer logs, and underground markets. Rate limiting is the cheapest first control you can put in front of that traffic. Done well, it turns a stuffing campaign into a handful of failed logins. Done poorly, it either locks out everyone behind a corporate NAT or lets attackers grind through millions of pairs.
The work is not picking one algorithm. You have to tune the algorithm, the key, and the response together. The rest of this post is that combination: algorithms, keying, and the integration patterns that actually stop brute force instead of looking like they do.
Algorithm Choices: Token Bucket, Leaky Bucket, and Sliding Window
The three canonical rate limiting algorithms each behave differently under burst traffic, and picking the wrong one for authentication can let attacks through.
Token Bucket
In the token bucket model, each key has a bucket that holds up to N tokens. Tokens refill at a steady rate, and every request consumes one. When the bucket is empty, requests are rejected. Token bucket is forgiving of short bursts, which matches legitimate human behavior: a user who mistypes their password twice and then succeeds on the third attempt looks healthy.
- Pros: Simple to implement in Redis with INCR and EXPIRE, tolerates bursts, memory efficient.
- Cons: Attackers can learn the burst size and pace requests to stay just under it.
Leaky Bucket
Leaky bucket enforces a strict outflow rate. Requests queue into the bucket and drain at a fixed interval. If the queue overflows, requests are dropped. It smooths traffic aggressively, which is useful for downstream protection but can feel punitive on login endpoints where legitimate users expect instant responses.
Sliding Window Log and Sliding Window Counter
Sliding window algorithms track request counts over a moving time window. The sliding window log stores every request timestamp (accurate but expensive), while the sliding window counter approximates by weighting the previous fixed window. For authentication, the sliding window counter is usually the sweet spot: accurate enough to catch slow drip attacks, cheap enough to run at millions of requests per second.
For most login endpoints, we recommend a hybrid: token bucket for short term burst control, layered with a sliding window counter for longer horizon limits (e.g., 5 attempts per minute, 20 per hour, 100 per day).
Keying Strategy: Per IP, Per Account, Per Device
The algorithm is the easy half. What you key on decides which attacks you actually stop.
Per IP Rate Limiting
The default. Key the counter on the client IP address. This stops naive single source brute force instantly. It is also the strategy most likely to cause false positives, because large numbers of legitimate users share IPs through corporate NAT, carrier grade NAT (CGNAT), VPN exit nodes, and mobile networks. A single CGNAT gateway can front hundreds of thousands of subscribers.
Mitigations:
- Maintain an allowlist or softer threshold for known shared infrastructure (mobile carrier ranges, enterprise egress).
- Combine IP with user agent and ASN for a coarser fingerprint.
- Raise per IP limits high and rely on per account keys for the real enforcement.
Per Account Rate Limiting
Key the counter on the username or email being attempted, not the source IP. This is the only effective defense against credential stuffing from distributed residential proxy networks, where each request may come from a different IP. Per account limits should be strict: 5-10 failed attempts per hour before escalation.
Watch out for username enumeration: rate limiting based on account existence leaks which accounts are real. Always apply the same limit to requests for nonexistent accounts, and return identical error responses.
Per Device Fingerprinting
Device fingerprinting (canvas, WebGL, audio context, installed fonts, hardware concurrency) produces a stable identifier that survives IP rotation. Combined with passive TLS fingerprints like JA3 and JA4, it lets you rate limit the actual attacker tool even when it cycles through thousands of proxies. This is the most powerful key for sophisticated credential stuffing, but it requires client side instrumentation and a fingerprinting service.
Handling NAT, CGNAT, and Shared Infrastructure
Mobile networks and corporate egress gateways are the hardest cases. A single public IP may represent an entire office or an entire city block. Hard blocking that IP takes down thousands of users.
Recommended patterns:
- Tiered thresholds: Track the ratio of unique usernames to requests from the same IP. A healthy shared IP sees many users each attempting their own credentials. A credential stuffing source sees many usernames from a narrow set of automation signatures.
- ASN awareness: Apply different limits to residential ISPs, cloud providers, and known hosting networks. Requests from AWS, Hetzner, or OVH hitting a consumer login page almost never represent legitimate users.
- Challenge instead of block: When a shared IP crosses a threshold, issue a CAPTCHA or step up challenge rather than a hard 429. This preserves legitimate access while costing automation real money.
Exponential Backoff vs Hard Lockout
Once an attacker crosses a threshold, what do you do? Two schools of thought.
Hard Lockout
Lock the account or IP for a fixed duration (15 minutes, 1 hour, 24 hours). Simple, deterministic, and effective against low volume attacks. The downside is denial of service: an attacker who knows a target username can lock the victim out of their own account indefinitely by hammering the endpoint.
Exponential Backoff
Double the delay with each failed attempt (1s, 2s, 4s, 8s, 16s, 32s...). The legitimate user barely notices on their first retry, but an attacker grinding credentials hits a wall within seconds. Exponential backoff resists the denial of service problem because legitimate users can still eventually log in.
For account level protection, we recommend exponential backoff on failures combined with a sliding window hard cap (e.g., no more than 20 attempts per account per hour regardless of source).
Integration with Bot Scoring and Device Signals
Rate limiting in isolation cannot stop modern credential stuffing. Attackers use residential proxy networks that rotate IPs on every request, solve CAPTCHAs via human farms or ML models, and mimic browser fingerprints. Effective defense requires layered signals:
- Bot scoring: Behavioral analytics (mouse movement, typing cadence, form interaction timing) score each request on a likelihood scale. Rate limits tighten as bot scores rise.
- TLS fingerprints: JA3/JA4 fingerprints identify automation frameworks (Puppeteer, Playwright, headless Chrome variants) even when user agent strings are spoofed.
- Credential intelligence: Check submitted credentials against known compromised password databases before accepting them. If a user is attempting a password that appears in breach data tied to that same email, treat every attempt as high risk. Revealer's data breach lookup checks whether an email appears in known breach datasets, which is one source for that signal.
- CAPTCHA as a scalpel: Do not show CAPTCHA to everyone. Show it only when rate limit thresholds or bot scores indicate elevated risk. This preserves UX for 99 percent of users while forcing automation to pay a cost.
Why Rate Limiting Alone Is Not Enough
A well funded stuffing operation will walk through any single control. Attackers map MITRE ATT&CK T1110.004 (Credential Stuffing) like this:
- Purchase combo lists from infostealer log aggregators.
- Rent residential proxies across 50+ countries at less than a cent per IP.
- Distribute the attack so no single IP exceeds 2-3 requests per minute.
- Rotate device fingerprints and solve CAPTCHAs on the fly.
- Harvest successful logins silently over days or weeks.
Against that adversary, per IP rate limiting is irrelevant. Per account limits help, but require enumeration protection. Device fingerprinting helps until the attacker swaps tools. The only durable defense is layered detection that combines all of these signals plus continuous monitoring of credential exposure outside your perimeter.
Frequently asked questions
What is the best rate limiting algorithm for login endpoints?
A hybrid. Token bucket handles short bursts so a user who mistypes twice is not punished, and a sliding window counter enforces longer-horizon limits like 20 attempts per hour. Leaky bucket is usually too punitive for interactive login flows.
Should I rate limit by IP or by account?
Both, for different reasons. Per IP limits stop naive single-source brute force but produce false positives behind NAT and CGNAT. Per account limits are the only reliable defense against distributed credential stuffing, since every request may arrive from a different IP.
What thresholds are reasonable for login attempts?
A common starting point is 5 attempts per minute, 20 per hour, and 100 per day per key, with per account limits escalating after 5-10 failed attempts in an hour. Tune from your own traffic: thresholds that are right for a consumer app may be wrong for an enterprise SSO.
Does rate limiting stop credential stuffing?
Not alone. Distributed stuffing attacks stay under per IP limits by design, rotating residential proxies and device fingerprints per request. Rate limiting eliminates unsophisticated, high-volume attacks; per account keying, device fingerprinting, bot scoring, and credential intelligence handle the rest.
Is account lockout a good idea?
Fixed lockouts are simple and effective against low-volume attacks, but they hand attackers a denial-of-service lever against any known username. Exponential backoff combined with a hard per-account cap gives attackers the same wall without locking legitimate users out entirely.
How do I avoid blocking users behind CGNAT?
Do not hard block shared IPs. Track the ratio of unique usernames to requests from each IP, apply ASN-aware thresholds so hosting networks get stricter treatment than residential ISPs, and issue a challenge instead of a 429 when a shared IP crosses a threshold.
Conclusion
Rate limiting is required and still not enough. Get it right and you drop the 95 percent of attacks that come from cheap bots and single-source scripts. Add per-account keying, exponential backoff, device fingerprinting, bot scoring, and credential intelligence, and stuffing starts to cost more than most crews will pay.
Nobody needs an uncrackable login page. They need one that costs more to attack than the attacker will spend. Layered rate limiting plus live credential-exposure monitoring is how you get there.
Want to check whether the credentials behind your login flow already appear in known breach datasets? Start a free trial of Revealer.US and catch stuffing attacks before they land.