{
    "slug": "rate_limiting",
    "term": "Rate Limiting",
    "category": "performance",
    "difficulty": "intermediate",
    "short": "Restricting the number of requests a client can make in a given time window to prevent abuse, DoS, and credential stuffing.",
    "long": "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.",
    "aliases": [
        "request throttling",
        "API rate limit",
        "token bucket"
    ],
    "tags": [
        "performance",
        "security",
        "api",
        "infrastructure"
    ],
    "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."
    ],
    "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."
    ],
    "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."
    ],
    "related": [
        "dos_attack",
        "brute_force",
        "credential_stuffing",
        "backpressure"
    ],
    "prerequisites": [
        "brute_force",
        "api_rate_limiting_design",
        "redis_patterns"
    ],
    "refs": [
        "https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html"
    ],
    "bad_code": "// No rate limiting — login endpoint accepts unlimited attempts",
    "good_code": "$key = 'login_attempts:' . $ip;\n$attempts = $redis->incr($key);\nif ($attempts === 1) $redis->expire($key, 300);\nif ($attempts > 5) { http_response_code(429); exit; }",
    "quick_fix": "Implement token bucket or sliding window rate limiting on login, registration, password reset, and all API endpoints using Redis",
    "severity": "high",
    "effort": "medium",
    "created": "2026-03-13",
    "updated": "2026-03-25",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/rate_limiting",
        "html_url": "https://codeclaritylab.com/glossary/rate_limiting",
        "json_url": "https://codeclaritylab.com/glossary/rate_limiting.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Rate Limiting](https://codeclaritylab.com/glossary/rate_limiting) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/rate_limiting"
            }
        }
    }
}