← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Rate Limiting

Performance CWE-770 OWASP A5:2021 PHP 5.0+ Intermediate
debt(d7/e5/b5/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7) — owasp-zap and semgrep can flag missing rate limit middleware patterns but this is largely a security review concern; absence of rate limiting is invisible to typical CI.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5) — quick_fix says implement token bucket/sliding window with Redis across login, registration, password reset, and API endpoints. Not a one-liner; requires middleware setup, storage backend, and applying to many routes.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5) — applies across all web/api contexts; every new endpoint must consider rate limit policy, key strategy (user+IP+API key), and headers. Ongoing tax but not architecture-defining.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7) — misconception states IP-only rate limiting feels obviously correct but is defeated by NAT, proxies, and botnets; the intuitive implementation is materially wrong and gives false sense of security.

About DEBT scoring →

Also Known As

request throttling API rate limit token bucket

TL;DR

Restricting the number of requests a client can make in a given time window to prevent abuse, DoS, and credential stuffing.

Explanation

Rate limiting enforces request quotas per user, IP, or API key. Algorithms include: Fixed Window (simple counter per time window — vulnerable to burst at window boundary), Sliding Window (smoothed count over a rolling period), Token Bucket (tokens refill at a rate; bursts allowed up to bucket size), and Leaky Bucket (requests drain at a fixed rate, excess queued or dropped). In PHP, implement with Redis using atomic Lua scripts or the INCR/EXPIRE pattern. Return 429 Too Many Requests with a Retry-After header. Apply at multiple layers: Nginx/Caddy at the network edge, application middleware for per-user limits.

Common Misconception

Rate limiting by IP address is sufficient to prevent abuse. IPs can be shared (NAT, corporate proxies) or spoofed, and attackers use distributed botnets. Rate limit by authenticated user ID, API key, and IP in combination for meaningful protection.

Why It Matters

Without rate limiting, login endpoints are open to brute-force attacks, APIs can be abused by scrapers, and a single misbehaving client can exhaust server resources for everyone. Rate limiting is the first line of defence against automated abuse.

Common Mistakes

  • Rate limiting per IP only — attackers use distributed botnets with thousands of different IPs.
  • Applying rate limits only to authentication routes and ignoring expensive API endpoints.
  • Returning 200 OK with a fake success response instead of 429 — attackers cannot detect the limit.
  • Not including Retry-After headers — legitimate clients cannot back off gracefully.

Avoid When

  • Internal service-to-service calls on a trusted network — rate limiting adds latency and complexity with no security benefit.
  • The rate limit is set so high it never triggers — a limit that is never hit protects nothing.
  • Applied without clear error responses — clients must receive a 429 with Retry-After so they can back off correctly.
  • Using IP-based limiting alone for authenticated APIs — one IP may serve many legitimate users behind a NAT.

When To Use

  • Any public-facing API endpoint to prevent abuse, scraping, and denial-of-service.
  • Authentication endpoints — rate limiting login and password-reset prevents brute force attacks.
  • Expensive operations (email sending, PDF generation, ML inference) that must be protected from runaway consumers.
  • Per-user or per-API-key limits to enforce fair usage in multi-tenant SaaS products.

Code Examples

✗ Vulnerable
// No rate limiting — login endpoint accepts unlimited attempts
✓ Fixed
$key = 'login_attempts:' . $ip;
$attempts = $redis->incr($key);
if ($attempts === 1) $redis->expire($key, 300);
if ($attempts > 5) { http_response_code(429); exit; }

Added 13 Mar 2026
Edited 25 Mar 2026
Views 73
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 1 ping T 3 pings F 3 pings S 11 pings S 3 pings M 2 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W
No pings yet today
PetalBot 1
Scrapy 22 Amazonbot 10 Perplexity 7 Google 5 Ahrefs 4 SEMrush 4 Unknown AI 2 ChatGPT 2 Claude 2 Qwen 1 PetalBot 1
crawler 55 crawler_json 5
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Implement token bucket or sliding window rate limiting on login, registration, password reset, and all API endpoints using Redis
📦 Applies To
PHP 5.0+ web api
🔗 Prerequisites
🔍 Detection Hints
Login or auth endpoint with no rate limit middleware or missing X-RateLimit headers
Auto-detectable: ✗ No owasp-zap semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update
CWE-770 CWE-400


✓ schema.org compliant