API Rate Limiting: Implementation Strategies and Best Practices

API Rate Limiting: Implementation Strategies and Best Practices


Disclosure: This article may contain affiliate links. We only recommend products we believe in.

Why Rate Limit?

Without rate limiting, a single client (malicious or buggy) can overwhelm your API, degrading service for all users. Rate limiting protects availability, prevents abuse, controls costs, and ensures fair resource allocation.

Common Algorithms

1. Token Bucket

Imagine a bucket that holds tokens. Each request consumes one token. Tokens are added at a fixed rate. When the bucket is empty, requests are rejected until tokens refill.

Pros: Allows bursts (up to bucket capacity), smooth rate over time. Cons: Slightly more complex to implement.

2. Sliding Window

Count requests within a rolling time window. If the count exceeds the limit, reject new requests.

Pros: Simple to understand and implement. Cons: Can allow 2x the limit at window boundaries (fixed with sliding window log).

3. Fixed Window

Count requests within fixed time intervals (e.g., per minute). Reset the counter at each interval boundary.

Pros: Simplest to implement. Cons: Allows burst at window boundaries. Two rapid bursts at the end and start of adjacent windows can double the effective rate.

Implementation with Redis

import redis
import time

r = redis.Redis()

def rate_limit(client_id: str, max_requests: int = 100, window_seconds: int = 60) -> bool:
    key = f"rate_limit:{client_id}"
    current = r.get(key)
    
    if current is None:
        r.setex(key, window_seconds, 1)
        return True
    elif int(current) < max_requests:
        r.incr(key)
        return True
    else:
        return False

HTTP Response Standards

When rate limiting, return proper HTTP headers:

HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1620000000

Tiered Rate Limits

Different limits for different user tiers:

  • Free tier: 100 requests/minute
  • Pro tier: 1,000 requests/minute
  • Enterprise: 10,000 requests/minute

Distributed Rate Limiting

In a multi-server deployment, each server needs to check against a shared counter (Redis, Memcached). Local-only counters allow N times the intended rate (where N is the number of servers).

For more on this topic, see our guide on AI Code Generation Security: Best Practices Every Developer Needs.