All Resources
Guide
BackendAPIPerformance
June 11, 2024

API Rate Limiting Strategies

Implement effective rate limiting to protect your API from abuse and overload.

Overview

Rate limiting protects APIs from abuse, ensures fair usage, and prevents DDoS attacks. Learn multiple strategies and implementations.

Common Strategies

  • Token Bucket: Smooth rate limiting with burst support
  • Sliding Window: Accurate request counting
  • Fixed Window: Simple but prone to burst at boundaries
  • Leaky Bucket: Smooth output rate
  • Adaptive: Dynamic limits based on server load

Token Bucket Algorithm

interface RateLimiter {
  tokens: number
  lastRefill: number
  maxTokens: number
  refillRate: number // tokens per second
}

function isAllowed(limiter: RateLimiter): boolean {
  const now = Date.now() / 1000
  const timePassed = now - limiter.lastRefill
  
  // Refill tokens
  limiter.tokens = Math.min(
    limiter.maxTokens,
    limiter.tokens + timePassed * limiter.refillRate
  )
  limiter.lastRefill = now

  if (limiter.tokens >= 1) {
    limiter.tokens -= 1
    return true
  }
  
  return false
}

// Usage: 100 requests per second with burst of 200
const limiter: RateLimiter = {
  tokens: 200,
  lastRefill: Date.now() / 1000,
  maxTokens: 200,
  refillRate: 100
}

Redis-based Implementation

import redis from 'redis'

const client = redis.createClient()

async function rateLimit(userId: string, limit: number, window: number) {
  const key = `ratelimit:${userId}`
  const count = await client.incr(key)

  if (count === 1) {
    await client.expire(key, window)
  }

  return count <= limit
}

// Express middleware
app.use(async (req, res, next) => {
  const allowed = await rateLimit(req.ip, 100, 60)
  
  res.set('X-RateLimit-Limit', '100')
  res.set('X-RateLimit-Remaining', String(Math.max(0, 100 - count)))
  
  if (!allowed) {
    return res.status(429).json({ error: 'Too many requests' })
  }
  
  next()
})

Tiered Rate Limiting

const limits = {
  free: { requests: 100, window: 3600 },
  pro: { requests: 1000, window: 3600 },
  enterprise: { requests: Infinity, window: Infinity }
}

async function checkRateLimit(userId: string, tier: 'free' | 'pro' | 'enterprise') {
  const limit = limits[tier]
  return rateLimit(userId, limit.requests, limit.window)
}

Well-implemented rate limiting reduces API costs by 40-60% by preventing abuse.

Curated by

Shyam