Skip to main content

Rate Limiting

Medium

429 Too Many Requests

Rate limiting protects APIs from abuse, brute force, and DoS by capping how many requests a client can make in a time window. Return HTTP 429 Too Many Requests with a Retry-After header when the limit is exceeded. Implement at the API gateway or reverse proxy layer, not in application code.

Overview

Rate limiting is essential for any public-facing API. Without it, a single client can send unlimited requests – exhausting your server resources, brute-forcing passwords, scraping your content, or triggering excessive third-party API costs.

Common rate limiting strategies: fixed window (reset at interval boundary, susceptible to burst at reset), sliding window (better distribution), token bucket (burst allowance with sustained rate limit), and leaky bucket (constant output rate regardless of input bursts).

The HTTP response for a rate-limited request is 429 Too Many Requests. The Retry-After header tells the client when to retry. Clients that implement exponential backoff with jitter reduce thundering herd problems when limits reset.

Differentiated limits by tier (authenticated vs anonymous, paid vs free) are standard practice. Rate limit by IP for anonymous requests, by API key or user ID for authenticated requests.

The Attack: Credential Stuffing / Brute Force Without Rate Limiting

Without rate limiting, attackers can attempt thousands of password guesses per second. A typical leaked credential database has millions of username/password pairs that work across many services.

Brute force without rate limiting
http
# Attacker sends 10,000 login attempts per minute
POST /api/auth/login HTTP/1.1
Content-Type: application/json
{"email":"[email protected]","password":"Password1"}

POST /api/auth/login HTTP/1.1
{"email":"[email protected]","password":"Password123"}

# ... 9,998 more attempts with no throttling

Defenses

1Return 429 with Retry-After

When the rate limit is exceeded, return 429 Too Many Requests with a Retry-After header specifying when the client can retry. Use seconds (integer) or an HTTP-date for the value.

Rate limit response
http
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1735689600
Content-Type: application/json

{"error":"rate_limit_exceeded","retry_after":60}

2Expose rate limit headers proactively

Well-behaved API clients can self-throttle if you tell them their current limit status on every response. Include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers before the limit is hit.

Rate limit headers on normal response
http
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1735689600
Content-Type: application/json

Checklist

  • Implement rate limiting at the API gateway layer (Nginx, Cloudflare, Kong) for zero-latency rejection
  • Return 429 with Retry-After – do not return 503 for rate limiting
  • Rate limit by user ID for authenticated requests, by IP for anonymous requests
  • Differentiate limits by tier: auth endpoints get stricter limits than data endpoints
  • Include X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset on all API responses
  • Implement exponential backoff with jitter in API clients to prevent thundering herd on reset
  • Log and alert on sustained 429 rates – indicates an attack or misbehaving client

Related Headers

Related Status Codes

FAQ

Should I return 429 or 503 for rate limiting?

Return 429 Too Many Requests. 503 Service Unavailable means the server is temporarily unable to handle any requests. 429 specifically means this client has exceeded its rate limit while the service is otherwise healthy. Clients and monitoring systems treat them differently.

What is the difference between rate limiting and throttling?

Rate limiting rejects excess requests outright (429). Throttling slows them down by adding delay before processing. Rate limiting is more appropriate for APIs – it gives clients clear feedback to implement backoff. Throttling is useful for protecting downstream services from being overwhelmed.