Rate Limiting Guide

Algorithm Comparison

Token Bucket

Tokens added at constant rate. Requests consume tokens. Allows bursts up to bucket size.

โœ“ Handles bursts, smooth average rate
Leaky Bucket

Requests queue up. Processed at constant rate regardless of input. Very smooth output.

โœ“ Smooth output, no bursts
Fixed Window

N requests allowed per time window (e.g., 100/min). Resets at window boundary. Simple but edge-case burst possible.

โœ“ Simple, easy to understand
Sliding Window

Counts requests in rolling time window. More accurate than fixed window. Higher memory usage.

โœ“ Accurate, no edge burst

Standard Rate Limit Headers

# Response headers (IETF draft standard)
RateLimit-Limit: 100        # max requests per window
RateLimit-Remaining: 45     # requests left
RateLimit-Reset: 1704067200 # Unix timestamp when window resets

# When limit exceeded: 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Retry-After: 30             # seconds to wait

Redis Token Bucket (Go example)

// Using go-redis with token bucket pattern
func rateLimitCheck(ctx context.Context, rdb *redis.Client, key string, limit int, window time.Duration) bool {
    pipe := rdb.Pipeline()
    now := time.Now().Unix()
    windowStart := now - int64(window.Seconds())

    // Remove expired entries
    pipe.ZRemRangeByScore(ctx, key, "-inf", strconv.FormatInt(windowStart, 10))
    // Count current window
    pipe.ZCard(ctx, key)
    // Add new request
    pipe.ZAdd(ctx, key, &redis.Z{Score: float64(now), Member: now})
    pipe.Expire(ctx, key, window)

    results, _ := pipe.Exec(ctx)
    count := results[1].(*redis.IntCmd).Val()
    return count < int64(limit)
}

Recommended Limits by API Type

API TypeTypical LimitNotes
Public read API1000/hourUnauthenticated users
Authenticated API5000/hourPer API key
Write/mutation API100/minutePer user
Login endpoint10/minuteBrute force prevention
Email/SMS sending5/minutePer user per action