Without rate limiting, a single user — or a bot — can make thousands of requests per second to your API, overwhelming your servers, degrading performance for everyone, and running up your infrastructure costs. Rate limiting protects your API by restricting how many requests a client can make in a given time window.

Why Rate Limit?

  • Prevent abuse: Block brute-force login attempts, spam, and data scraping
  • Protect resources: Prevent a single user from hogging server capacity
  • Ensure fairness: Give all users equal access to your API
  • Control costs: Limit expensive operations (AI inference, database queries)
  • SLA compliance: Enforce usage tiers in your API pricing plans

Rate Limiting Algorithms

1. Fixed Window

Count requests in fixed time intervals (e.g., per minute). When the counter exceeds the limit, reject until the next window.

Fixed Window
Window: 1 minute | Limit: 100 requests

12:00:00 - 12:00:59 → Request 1...100 ✅ | Request 101 ❌
12:01:00 - 12:01:59 → Counter resets → Request 1...100 ✅

⚠️ Problem: A user can send 100 requests at 12:00:59
and another 100 at 12:01:00 — 200 requests in 2 seconds!

2. Sliding Window Log

Track the timestamp of every request. Count requests in the last N seconds. Most accurate but memory-intensive.

3. Sliding Window Counter

Combines fixed window and sliding window. Uses weighted average of current and previous window counts. Good balance of accuracy and memory.

4. Token Bucket (Recommended)

A "bucket" holds tokens. Each request consumes a token. Tokens are added at a fixed rate. If the bucket is empty, requests are rejected. Allows short bursts while enforcing an average rate.

Token Bucket Concept
Bucket capacity: 10 tokens
Refill rate: 1 token/second

Second 0:  Bucket has 10 tokens
           → User sends 5 requests → 5 tokens consumed → 5 remaining
Second 1:  1 token added → 6 tokens
           → User sends 1 request → 5 remaining
Second 5:  4 tokens added → 9 tokens
           → User sends burst of 9 → 0 remaining
Second 6:  1 token added → 1 token
           → User can make 1 request

Implementation with Redis

Express.js + Redis Sliding Window
import Redis from 'ioredis';
const redis = new Redis();

async function rateLimiter(req, res, next) {
  const key = `rate:${req.ip}`;
  const limit = 100;           // requests
  const windowMs = 60 * 1000;  // per minute

  const now = Date.now();
  const windowStart = now - windowMs;

  // Atomic Redis operations
  const pipeline = redis.pipeline();
  pipeline.zremrangebyscore(key, 0, windowStart); // Remove old entries
  pipeline.zadd(key, now, `${now}-${Math.random()}`); // Add current request
  pipeline.zcard(key);                             // Count requests in window
  pipeline.expire(key, 60);                        // Auto-cleanup

  const results = await pipeline.exec();
  const requestCount = results[2][1];

  // Set rate limit headers
  res.set({
    'X-RateLimit-Limit': limit,
    'X-RateLimit-Remaining': Math.max(0, limit - requestCount),
    'X-RateLimit-Reset': Math.ceil((now + windowMs) / 1000),
  });

  if (requestCount > limit) {
    res.set('Retry-After', '60');
    return res.status(429).json({
      error: 'Too Many Requests',
      message: 'Rate limit exceeded. Please try again later.',
      retryAfter: 60,
    });
  }

  next();
}

app.use('/api/', rateLimiter);

Rate Limit Headers

Standard Headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 100          // Max requests per window
X-RateLimit-Remaining: 73       // Requests remaining
X-RateLimit-Reset: 1720396800   // Unix timestamp when window resets

HTTP/1.1 429 Too Many Requests
Retry-After: 60                 // Seconds until client can retry
Content-Type: application/json
{
  "error": "Too Many Requests",
  "retryAfter": 60
}

Best Practices

  • Rate limit by API key for authenticated users, by IP for anonymous users
  • Use different limits for different endpoints — login endpoints need stricter limits than read-only endpoints
  • Return informative 429 responses with Retry-After header
  • Include rate limit headers on every response so clients can self-regulate
  • Use Redis for distributed rate limiting across multiple server instances
  • Consider tiered limits — free users get 100/min, paid users get 1000/min
  • Don't rate limit health check endpoints — monitoring services need unrestricted access

Try Our Free Developer Tools

Format and validate your API responses instantly.