Rate Limiting and Its Role in Application Security
Rate limiting tends to get owned by infrastructure or platform teams and framed as a cost and reliability concern — stop one client from overwhelming shared resources. That framing misses half of what rate limiting actually does. Without it, a huge range of attacks that are individually trivial to detect become practically unstoppable simply because nothing prevents an attacker from trying them at scale, quickly, and repeatedly.
What rate limiting actually defends against
Credential stuffing and brute-force login attempts. Without a limit on login attempts, an attacker with a list of leaked username/password pairs from an unrelated breach can test all of them against your login endpoint at whatever speed your infrastructure allows. A single correct guess in a large list is often all that's needed, and the individual requests look like ordinary login attempts — the abuse is entirely a function of volume and speed, which rate limiting directly constrains.
Account and data enumeration. Registration, password reset, and "check if username is available" endpoints often leak whether a given identifier exists in the system through subtly different responses. Rate limiting doesn't fix the underlying information leak, but it drastically slows down an attacker's ability to enumerate a large list of identifiers against it.
OTP and MFA brute-forcing. A six-digit one-time code has a million possible values — trivial to exhaust with unlimited attempts at reasonable request speed, and a control that's frequently implemented without any limit on verification attempts because the "happy path" testing never exercises repeated wrong guesses.
Scraping and data harvesting. Public or semi-public API endpoints without rate limiting are an open invitation to have your entire dataset — pricing, inventory, user-generated content — systematically extracted by a competitor or scraper, one page or request at a time, indistinguishable from legitimate traffic at the level of any individual request.
Resource exhaustion via expensive operations. Endpoints that trigger costly backend work — report generation, complex search queries, bulk export, image processing — can be used to degrade service or inflate infrastructure costs even without malicious intent behind each individual call, simply by triggering them faster than the backend can sustainably process.
Designing rate limits that actually hold
Limit by identity, not just IP. IP-based rate limiting is the easiest to implement and the easiest to defeat — residential proxy networks and distributed botnets make IP rotation trivial and cheap. For any authenticated endpoint, rate limit by user ID or API key in addition to IP, since that's a much harder identifier for an attacker to rotate.
Differentiate sensitive endpoints. A blanket global rate limit tuned for general API traffic is usually far too permissive for login, password reset, and MFA verification endpoints specifically. These should have their own, much stricter limits, ideally with progressive backoff (increasing delay after repeated failures) rather than a flat threshold.
Respond carefully when the limit is hit. A rate limit response that reveals too much — a different message for "wrong password" versus "you're rate limited" — can itself leak information. Conversely, silently dropping requests instead of returning a clear 429 makes debugging legitimate client behavior unnecessarily hard. Aim for a response that's informative to a legitimate client without giving an attacker a clean signal to calibrate their attack speed against.
Don't rely on rate limiting alone for authentication security. Rate limiting raises the cost of an attack; it doesn't eliminate it against a patient, low-and-slow attacker operating just under the threshold. It should be paired with anomaly detection (many failed logins across different accounts from one source), CAPTCHA challenges triggered by suspicious patterns, and account lockout policies with sensible thresholds.
Test rate limits as part of the security assessment, not just load testing. Confirm the limit is actually enforced server-side (not just advertised in API documentation), confirm it can't be trivially bypassed by rotating a header the backend mistakenly trusts (like X-Forwarded-For without proper proxy validation), and confirm it applies consistently across every path that reaches the protected functionality, including any internal or mobile-specific API routes.
A practical checklist
- Rate limit authentication, password reset, and MFA verification endpoints more strictly than general API traffic.
- Key rate limits on authenticated identity where possible, not solely on source IP.
- Validate that IP-derived rate limiting can't be bypassed via spoofable headers when the app sits behind a proxy or load balancer.
- Add progressive backoff and account-level lockout for repeated authentication failures, layered on top of request-level rate limiting.
- Include rate-limit bypass testing explicitly in every assessment scope, since it's easy for a control to exist in code but be misconfigured or reachable through an unprotected alternate path.
Rate limiting is one of the clearer examples of a control that needs both automated verification and manual adversarial testing — a scanner can confirm a 429 response exists, but only a tester deliberately trying header spoofing, distributed source IPs, and alternate endpoint paths can confirm the control actually holds under realistic attack conditions. Venstap's scan templates include rate-limit and brute-force checks as a standard part of scoped engagements, with findings tracked alongside authentication and access-control issues so gaps in this control don't get treated as a lower-priority afterthought.
Ready to see Venstap in action?
Get a guided walkthrough of scanning, triage, and reporting on your own assets.