Rate Limiting & Account Lockout:Stop Brute Force Attacks
Almost every authentication attack: brute force, credential stuffing, password spraying: works by making many login attempts quickly. Rate limiting and account lockout are the two controls that make that expensive. This guide explains how each works, where each fits, and how to combine them without locking out your real users. It is the companion to our deep dives on brute force attacks and credential stuffing.
What Is Rate Limiting?
Rate limiting restricts how many requests a client can make to an endpoint within a fixed period: for example, 5 login attempts per minute per IP address. When the limit is exceeded, the server rejects further requests with an HTTP 429 Too Many Requests response until the window resets. Rate limiting is endpoint-centric: it protects the login route itself, regardless of which account is being targeted, which makes it the front-line defense against high-volume automated attacks.
What Is Account Lockout?
Account lockout disables a specific account after a threshold of consecutive failed login attempts: for example, locking the account for 15 minutes after 5 wrong passwords. It is account-centric: it protects one user from targeted guessing, even if the attacker rotates IP addresses to evade rate limiting. The trade-off is that lockout can be abused to deny service: an attacker who knows a username can deliberately lock a victim out by submitting bad passwords.
Rate Limiting vs Account Lockout: What Is the Difference?
| Dimension | Rate Limiting | Account Lockout |
|---|---|---|
| Protects | The endpoint (all accounts) | A single account |
| Keyed on | IP, token, or device fingerprint | Username / account ID |
| Best against | Credential stuffing, high-volume bots | Targeted password guessing |
| Weakness | Distributed attacks rotate IPs | Can be abused to lock victims out (DoS) |
| Typical response | HTTP 429, temporary delay | Account disabled for a cooldown period |
These weaknesses are complementary, which is exactly why OWASP recommends running both. Rate limiting catches the broad automated traffic; account lockout (or better, account-specific throttling) catches the slow, targeted attacker who stays under the rate limit.
How Do You Implement Rate Limiting?
There are four common algorithms. They trade memory for accuracy at the edges of each window:
| Algorithm | How It Works | Trade-off |
|---|---|---|
| Fixed window | Counts requests per fixed interval (e.g. per minute) | Simple, but allows bursts at window boundaries |
| Sliding window | Counts requests over a rolling time window | Smoother, slightly more memory and compute |
| Token bucket | Tokens refill at a steady rate; each request spends one | Allows controlled bursts; widely used |
| Leaky bucket | Requests queue and drain at a constant rate | Smooths output; adds latency under load |
A minimal sliding-window limiter on an Express login route, backed by Redis, looks like this:
app.post('/login', async (req, res) => {
const key = `rl:login:${req.ip}`;
const hits = await redis.incr(key);
if (hits === 1) await redis.expire(key, 60); // 60s window
if (hits > 5) return res.status(429).send('Too many attempts');
// ...continue with authentication
});
Key it on more than the IP where you can: a combination of IP plus username, or a device fingerprint, makes it harder for attackers behind a single NAT or proxy pool to evade. Always apply the limit server-side; client-side throttling is trivially bypassed.
How Do You Implement Account Lockout Safely?
- Use a cooldown, not a permanent lock: lock for a short period (for example 15 minutes) and auto-unlock, so support tickets do not pile up.
- Prefer exponential backoff: double the delay after each failure (1s, 2s, 4s, 8s...) instead of a hard lock. This slows attackers without fully denying the legitimate user.
- Count failures per account, not just per IP: a distributed attack uses many IPs against one account.
- Never reveal lockout state to anonymous users in a way that confirms the username exists: keep error messages generic.
- Reset the counter on a successful login and notify the user by email when a lockout is triggered.
What Else Does OWASP Recommend?
- Multi-factor authentication (MFA): the single most effective control: even valid stolen passwords fail without the second factor.
- Breached-password checks: reject passwords known to be compromised. See checking breached passwords with HaveIBeenPwned.
- CAPTCHA after N failures: add friction for bots while leaving humans mostly unaffected.
- Device and location anomaly detection: step up verification when a login looks unusual.
- Generic error messages: never reveal whether the username or the password was wrong.
Rate Limiting and Lockout in Context
These controls are necessary but not sufficient on their own. They are most effective as part of a layered authentication strategy that also includes MFA, breached-password screening, and audit logging. Our authentication library, OwlAuth, ships with lockout hooks, breached-password detection, and audit logging built to the OWASP Authentication Cheat Sheet.