Skip to content
API Rate Limiting logo

API Rate Limiting

> **Skill Purpose:** API rate limiting implementation, throttling strategies, and abuse prevention patterns

Coverage-Creatives/zeus0installs0stars

SKILL.md

Full skill instructions

API Rate Limiting

Skill Purpose: API rate limiting implementation, throttling strategies, and abuse prevention patterns


Core Skill Pattern

Objective: Establish comprehensive API rate limiting patterns with configurable throttling, user-based limits, and abuse prevention.

Universal Pattern:

  1. Define rate limiting strategies and algorithms
  2. Create configurable limit rules and policies
  3. Set up user-based and endpoint-specific limiting
  4. Establish monitoring and alerting procedures
  5. Create rate limiting bypass and exception handling

Key Decisions (Project-Specific):

  • Rate limiting algorithm and strategy
  • Limit granularity (global, user, endpoint)
  • Storage mechanism for limit tracking
  • Monitoring and alerting requirements
  • Bypass policies and exception handling

Project-Specific Implementation Notes

Customize per project:

  • Rate limiting algorithm based on traffic patterns and requirements
  • Limit granularity based on API usage and business needs
  • Storage approach based on performance and scalability requirements
  • Monitoring depth based on service criticality
  • Bypass policies based on operational requirements

Example Implementation (API Rate Limiting Pattern)

Note: This is an example pattern for API rate limiting. Adapt rate limiting algorithms and storage based on your specific API requirements and infrastructure.

Prerequisites (Example)

  • API endpoints identified and categorized
  • Rate limiting requirements documented
  • Storage mechanism selected (Redis, database, memory)
  • Monitoring and alerting systems established

Example: API Rate Limiting Implementation

Framework-Specific Example: This demonstrates rate limiting patterns using token bucket algorithm. Adapt for your rate limiting algorithm and storage requirements.

1. Rate Limiting Algorithms

// Rate limiting algorithms
interface RateLimitAlgorithm {
  name: string;
  checkLimit(key: string, limit: number, window: number): Promise<RateLimitResult>;
  resetLimit(key: string): Promise<void>;
}

interface RateLimitResult {
  allowed: boolean;
  remaining: number;
  resetTime: number;
  retryAfter?: number;
}

// Token Bucket Algorithm
class TokenBucketAlgorithm implements RateLimitAlgorithm {
  name = 'token_bucket';
  
  constructor(private storage: RateLimitStorage) {}
  
  async checkLimit(key: string, limit: number, window: number): Promise<RateLimitResult> {
    const bucket = await this.storage.getBucket(key);
    const now = Date.now();
    
    // Initialize bucket if not exists
    if (!bucket) {
      await this.storage.setBucket(key, {
        tokens: limit,
        lastRefill: now,
        limit,
        window
      });
      return {
        allowed: true,
        remaining: limit - 1,
        resetTime: now + window
      };
    }
    
    // Refill tokens based on time elapsed
    const timeElapsed = now - bucket.lastRefill;
    const tokensToAdd = Math.floor((timeElapsed / window) * limit);
    const currentTokens = Math.min(bucket.tokens + tokensToAdd, limit);
    
    // Check if token available
    if (currentTokens >= 1) {
      // Consume token
      const updatedBucket = {
        ...bucket,
        tokens: currentTokens - 1,
        lastRefill: now
      };
      
      await this.storage.setBucket(key, updatedBucket);
      
      return {
        allowed: true,
        remaining: currentTokens - 1,
        resetTime: now + window
      };
    } else {
      // Calculate retry after time
      const timeToNextToken = Math.ceil((window / limit) * (1 - currentTokens));
      
      return {
        allowed: false,
        remaining: 0,
        resetTime: bucket.lastRefill + window,
        retryAfter: timeToNextToken
      };
    }
  }
  
  async resetLimit(key: string): Promise<void> {
    await this.storage.deleteBucket(key);
  }
}

// Sliding Window Algorithm
class SlidingWindowAlgorithm implements RateLimitAlgorithm {
  name = 'sliding_window';
  
  constructor(private storage: RateLimitStorage) {}
  
  async checkLimit(key: string, limit: number, window: number): Promise<RateLimitResult> {
    const now = Date.now();
    const windowStart = now - window;
    
    // Get existing requests in window
    const requests = await this.storage.getRequests(key, windowStart);
    
    if (requests.length < limit) {
      // Add current request
      await this.storage.addRequest(key, now);
      
      return {
        allowed: true,
        remaining: limit - requests.length - 1,
        resetTime: now + window
      };
    } else {
      // Find oldest request to calculate retry after
      const oldestRequest = Math.min(...requests);
      const retryAfter = Math.ceil((oldestRequest + window - now) / 1000);
      
      return {
        allowed: false,
        remaining: 0,
        resetTime: oldestRequest + window,
        retryAfter
      };
    }
  }
  
  async resetLimit(key: string): Promise<void> {
    await this.storage.deleteRequests(key);
  }
}

// Fixed Window Counter Algorithm
class FixedWindowAlgorithm implements RateLimitAlgorithm {
  name = 'fixed_window';
  
  constructor(private storage: RateLimitStorage) {}
  
  async checkLimit(key: string, limit: number, window: number): Promise<RateLimitResult> {
    const now = Date.now();
    const currentWindow = Math.floor(now / window) * window;
    const nextWindow = currentWindow + window;
    
    // Get current window count
    const count = await this.storage.getWindowCount(key, currentWindow);
    
    if (count < limit) {
      // Increment count
      await this.storage.incrementWindowCount(key, currentWindow);
      
      return {
        allowed: true,
        remaining: limit - count - 1,
        resetTime: nextWindow
      };
    } else {
      return {
        allowed: false,
        remaining: 0,
        resetTime: nextWindow,
        retryAfter: Math.ceil((nextWindow - now) / 1000)
      };
    }
  }
  
  async resetLimit(key: string): Promise<void> {
    await this.storage.deleteWindowCount(key);
  }
}

2. Rate Limiting Configuration

// Rate limiting configuration and rules
interface RateLimitRule {
  name: string;
  algorithm: string;
  limit: number;
  window: number; // in milliseconds
  scope: 'global' | 'user' | 'ip' | 'endpoint' | 'custom';
  keyGenerator?: (context: RateLimitContext) => string;
  bypass?: (context: RateLimitContext) => boolean;
  responseHeaders?: boolean;
  penalty?: PenaltyConfig;
}

interface PenaltyConfig {
  enabled: boolean;
  multiplier: number;
  duration: number;
  maxPenalty: number;
}

interface RateLimitContext {
  requestId: string;
  userId?: string;
  ipAddress?: string;
  endpoint?: string;
  method?: string;
  userAgent?: string;
  timestamp: number;
  metadata?: Record<string, any>;
}

class RateLimitConfig {
  private rules: Map<string, RateLimitRule> = new Map();
  private globalDefaults: Partial<RateLimitRule> = {
    algorithm: 'token_bucket',
    limit: 100,
    window: 60000, // 1 minute
    scope: 'user',
    responseHeaders: true
  };
  
  addRule(rule: RateLimitRule): void {
    this.rules.set(rule.name, rule);
  }
  
  getRule(name: string): RateLimitRule {
    const rule = this.rules.get(name);
    if (!rule) {
      throw new Error(`Rate limit rule ${name} not found`);
    }
    return { ...this.globalDefaults, ...rule };
  }
  
  listRules(): RateLimitRule[] {
    return Array.from(this.rules.values());
  }
  
  removeRule(name: string): void {
    this.rules.delete(name);
  }
  
  // Predefined common rules
  static createCommonRules(): RateLimitConfig {
    const config = new RateLimitConfig();
    
    // Global API limit
    config.addRule({
      name: 'global_api',
      algorithm: 'token_bucket',
      limit: 1000,
      window: 60000, // 1000 requests per minute
      scope: 'global',
      responseHeaders: true
    });
    
    // User-based limit
    config.addRule({
      name: 'user_requests',
      algorithm: 'sliding_window',
      limit: 100,
      window: 60000, // 100 requests per minute per user
      scope: 'user',
      keyGenerator: (context) => context.userId || `anonymous_${context.ipAddress}`,
      responseHeaders: true
    });
    
    // IP-based limit
    config.addRule({
      name: 'ip_requests',
      algorithm: 'fixed_window',
      limit: 200,
      window: 60000, // 200 requests per minute per IP
      scope: 'ip',
      keyGenerator: (context) => context.ipAddress || 'unknown',
      responseHeaders: true
    });
    
    // Endpoint-specific limits
    config.addRule({
      name: 'auth_endpoints',
      algorithm: 'token_bucket',
      limit: 10,
      window: 60000, // 10 auth requests per minute
      scope: 'endpoint',
      keyGenerator: (context) => context.endpoint || 'unknown',
      bypass: (context) => context.endpoint?.startsWith('/​health'),
      responseHeaders: true
    });
    
    // Sensitive operations
    config.addRule({
      name: 'sensitive_operations',
      algorithm: 'sliding_window',
      limit: 5,
      window: 300000, // 5 requests per 5 minutes
      scope: 'user',
      keyGenerator: (context) => context.userId || `anonymous_${context.ipAddress}`,
      penalty: {
        enabled: true,
        multiplier: 2,
        duration: 600000, // 10 minutes
        maxPenalty: 60 // Maximum 1 hour penalty
      }
    });
    
    return config;
  }
}

3. Rate Limiting Middleware

// Rate limiting middleware implementation
class RateLimitMiddleware {
  private algorithms: Map<string, RateLimitAlgorithm> = new Map();
  private config: RateLimitConfig;
  private storage: RateLimitStorage;
  
  constructor(config: RateLimitConfig, storage: RateLimitStorage) {
    this.config = config;
    this.storage = storage;
    
    // Register algorithms
    this.algorithms.set('token_bucket', new TokenBucketAlgorithm(storage));
    this.algorithms.set('sliding_window', new SlidingWindowAlgorithm(storage));
    this.algorithms.set('fixed_window', new FixedWindowAlgorithm(storage));
  }
  
  async checkRateLimit(ruleName: string, context: RateLimitContext): Promise<RateLimitResult> {
    const rule = this.config.getRule(ruleName);
    const algorithm = this.algorithms.get(rule.algorithm);
    
    if (!algorithm) {
      throw new Error(`Rate limiting algorithm ${rule.algorithm} not found`);
    }
    
    // Check bypass conditions
    if (rule.bypass && rule.bypass(context)) {
      return {
        allowed: true,
        remaining: Number.MAX_SAFE_INTEGER,
        resetTime: Date.now() + 86400000 // 24 hours from now
      };
    }
    
    // Generate limit key
    const key = this.generateLimitKey(rule, context);
    
    // Check limit
    const result = await algorithm.checkLimit(key, rule.limit, rule.window);
    
    // Apply penalty if needed
    if (!result.allowed && rule.penalty?.enabled) {
      await this.applyPenalty(key, rule.penalty, context);
    }
    
    return result;
  }
  
  async checkMultipleLimits(ruleNames: string[], context: RateLimitContext): Promise<RateLimitCheckResult> {
    const results: Map<string, RateLimitResult> = new Map();
    let overallAllowed = true;
    let mostRestrictive: RateLimitResult | null = null;
    
    for (const ruleName of ruleNames) {
      try {
        const result = await this.checkRateLimit(ruleName, context);
        results.set(ruleName, result);
        
        if (!result.allowed) {
          overallAllowed = false;
          
          // Track most restrictive limit
          if (!mostRestrictive || result.retryAfter! > mostRestrictive.retryAfter!) {
            mostRestrictive = result;
          }
        }
      } catch (error) {
        console.error(`Error checking rate limit for rule ${ruleName}:`, error);
        // Fail open - allow request but log error
        results.set(ruleName, {
          allowed: true,
          remaining: Number.MAX_SAFE_INTEGER,
          resetTime: Date.now() + 86400000
        });
      }
    }
    
    return {
      allowed: overallAllowed,
      results: Object.fromEntries(results),
      mostRestrictive: mostRestrictive || undefined
    };
  }
  
  private generateLimitKey(rule: RateLimitRule, context: RateLimitContext): string {
    if (rule.keyGenerator) {
      return rule.keyGenerator(context);
    }
    
    switch (rule.scope) {
      case 'global':
        return 'global';
      case 'user':
        return context.userId || `anonymous_${context.ipAddress}`;
      case 'ip':
        return context.ipAddress || 'unknown';
      case 'endpoint':
        return context.endpoint || 'unknown';
      case 'custom':
        return `${context.requestId}_${context.timestamp}`;
      default:
        return 'default';
    }
  }
  
  private async applyPenalty(key: string, penalty: PenaltyConfig, context: RateLimitContext): Promise<void> {
    // Get current penalty count
    const penaltyKey = `${key}_penalty`;
    const currentPenalty = await this.storage.getPenalty(penaltyKey) || 0;
    
    // Calculate new penalty
    const newPenalty = Math.min(currentPenalty + 1, penalty.maxPenalty);
    
    // Apply penalty duration
    const penaltyDuration = penalty.duration * Math.pow(penalty.multiplier, newPenalty - 1);
    
    // Store penalty
    await this.storage.setPenalty(penaltyKey, {
      count: newPenalty,
      expiresAt: Date.now() + penaltyDuration,
      reason: 'rate_limit_violation',
      context
    });
    
    console.log(`Applied rate limit penalty to ${key}: ${newPenalty} violations, duration: ${penaltyDuration}ms`);
  }
  
  // Express.js middleware example
  middleware(ruleNames: string[], options: MiddlewareOptions = {}) {
    return async (req: any, res: any, next: any) => {
      try {
        const context: RateLimitContext = {
          requestId: req.id || req.headers['x-request-id'] || this.generateRequestId(),
          userId: req.user?.id,
          ipAddress: req.ip || req.connection.remoteAddress,
          endpoint: req.route?.path || req.path,
          method: req.method,
          userAgent: req.headers['user-agent'],
          timestamp: Date.now(),
          metadata: {
            headers: req.headers,
            query: req.query
          }
        };
        
        const result = await this.checkMultipleLimits(ruleNames, context);
        
        if (!result.allowed) {
          const response: RateLimitResponse = {
            error: 'Rate limit exceeded',
            message: options.message || 'Too many requests',
            retryAfter: result.mostRestrictive?.retryAfter,
            resetTime: result.mostRestrictive?.resetTime,
            limits: result.results
          };
          
          // Set rate limit headers
          if (options.includeHeaders !== false) {
            res.set('X-RateLimit-Limit', this.getTotalLimit(result.results));
            res.set('X-RateLimit-Remaining', this.getTotalRemaining(result.results));
            res.set('X-RateLimit-Reset', Math.ceil((result.mostRestrictive?.resetTime || 0) / 1000));
            
            if (result.mostRestrictive?.retryAfter) {
              res.set('Retry-After', result.mostRestrictive.retryAfter);
            }
          }
          
          return res.status(429).json(response);
        }
        
        // Add rate limit info to request for downstream use
        req.rateLimit = {
          checked: true,
          results: result.results,
          remaining: this.getTotalRemaining(result.results)
        };
        
        next();
      } catch (error) {
        console.error('Rate limiting middleware error:', error);
        // Fail open - allow request but log error
        next();
      }
    };
  }
  
  private generateRequestId(): string {
    return `req_${Date.now()}_${Math.random().toString(36).substring(7)}`;
  }
  
  private getTotalLimit(results: Record<string, RateLimitResult>): number {
    return Object.values(results).reduce((sum, result) => sum + (result.remaining + 1), 0);
  }
  
  private getTotalRemaining(results: Record<string, RateLimitResult>): number {
    return Object.values(results).reduce((sum, result) => sum + result.remaining, 0);
  }
}

interface RateLimitCheckResult {
  allowed: boolean;
  results: Record<string, RateLimitResult>;
  mostRestrictive?: RateLimitResult;
}

interface MiddlewareOptions {
  message?: string;
  includeHeaders?: boolean;
}

interface RateLimitResponse {
  error: string;
  message: string;
  retryAfter?: number;
  resetTime?: number;
  limits: Record<string, RateLimitResult>;
}

4. Rate Limiting Storage

// Rate limiting storage abstraction
interface RateLimitStorage {
  // Token bucket operations
  getBucket(key: string): Promise<TokenBucket | null>;
  setBucket(key: string, bucket: TokenBucket): Promise<void>;
  deleteBucket(key: string): Promise<void>;
  
  // Sliding window operations
  getRequests(key: string, since: number): Promise<number[]>;
  addRequest(key: string, timestamp: number): Promise<void>;
  deleteRequests(key: string): Promise<void>;
  
  // Fixed window operations
  getWindowCount(key: string, window: number): Promise<number>;
  incrementWindowCount(key: string, window: number): Promise<void>;
  deleteWindowCount(key: string): Promise<void>;
  
  // Penalty operations
  getPenalty(key: string): Promise<number | null>;
  setPenalty(key: string, penalty: PenaltyInfo): Promise<void>;
  deletePenalty(key: string): Promise<void>;
}

interface TokenBucket {
  tokens: number;
  lastRefill: number;
  limit: number;
  window: number;
}

interface PenaltyInfo {
  count: number;
  expiresAt: number;
  reason: string;
  context: RateLimitContext;
}

// Redis implementation
class RedisRateLimitStorage implements RateLimitStorage {
  constructor(private redis: any) {}
  
  async getBucket(key: string): Promise<TokenBucket | null> {
    const data = await this.redis.get(`bucket:${key}`);
    return data ? JSON.parse(data) : null;
  }
  
  async setBucket(key: string, bucket: TokenBucket): Promise<void> {
    await this.redis.setex(`bucket:${key}`, Math.ceil(bucket.window / 1000), JSON.stringify(bucket));
  }
  
  async deleteBucket(key: string): Promise<void> {
    await this.redis.del(`bucket:${key}`);
  }
  
  async getRequests(key: string, since: number): Promise<number[]> {
    const requests = await this.redis.zrangebyscore(`requests:${key}`, since, '+inf');
    return requests.map(Number);
  }
  
  async addRequest(key: string, timestamp: number): Promise<void> {
    await this.redis.zadd(`requests:${key}`, timestamp, timestamp);
    await this.redis.expire(`requests:${key}`, 3600); // 1 hour expiry
  }
  
  async deleteRequests(key: string): Promise<void> {
    await this.redis.del(`requests:${key}`);
  }
  
  async getWindowCount(key: string, window: number): Promise<number> {
    const count = await this.redis.get(`window:${key}:${window}`);
    return count ? parseInt(count) : 0;
  }
  
  async incrementWindowCount(key: string, window: number): Promise<void> {
    const count = await this.redis.incr(`window:${key}:${window}`);
    await this.redis.expire(`window:${key}:${window}`, Math.ceil(window / 1000) + 60);
  }
  
  async deleteWindowCount(key: string): Promise<void> {
    await this.redis.del(`window:${key}:*`);
  }
  
  async getPenalty(key: string): Promise<number | null> {
    const data = await this.redis.get(`penalty:${key}`);
    return data ? JSON.parse(data).count : null;
  }
  
  async setPenalty(key: string, penalty: PenaltyInfo): Promise<void> {
    await this.redis.setex(`penalty:${key}`, Math.ceil((penalty.expiresAt - Date.now()) / 1000), JSON.stringify(penalty));
  }
  
  async deletePenalty(key: string): Promise<void> {
    await this.redis.del(`penalty:${key}`);
  }
}

// Memory implementation (for development/​testing)
class MemoryRateLimitStorage implements RateLimitStorage {
  private buckets = new Map<string, TokenBucket>();
  private requests = new Map<string, number[]>();
  private windows = new Map<string, number>();
  private penalties = new Map<string, PenaltyInfo>();
  
  async getBucket(key: string): Promise<TokenBucket | null> {
    return this.buckets.get(key) || null;
  }
  
  async setBucket(key: string, bucket: TokenBucket): Promise<void> {
    this.buckets.set(key, bucket);
  }
  
  async deleteBucket(key: string): Promise<void> {
    this.buckets.delete(key);
  }
  
  async getRequests(key: string, since: number): Promise<number[]> {
    const requests = this.requests.get(key) || [];
    return requests.filter(timestamp => timestamp >= since);
  }
  
  async addRequest(key: string, timestamp: number): Promise<void> {
    const requests = this.requests.get(key) || [];
    requests.push(timestamp);
    this.requests.set(key, requests);
  }
  
  async deleteRequests(key: string): Promise<void> {
    this.requests.delete(key);
  }
  
  async getWindowCount(key: string, window: number): Promise<number> {
    return this.windows.get(`${key}:${window}`) || 0;
  }
  
  async incrementWindowCount(key: string, window: number): Promise<void> {
    const current = this.windows.get(`${key}:${window}`) || 0;
    this.windows.set(`${key}:${window}`, current + 1);
  }
  
  async deleteWindowCount(key: string): Promise<void> {
    // Delete all windows for this key
    for (const [windowKey] of this.windows) {
      if (windowKey.startsWith(`${key}:`)) {
        this.windows.delete(windowKey);
      }
    }
  }
  
  async getPenalty(key: string): Promise<number | null> {
    const penalty = this.penalties.get(key);
    return penalty ? penalty.count : null;
  }
  
  async setPenalty(key: string, penalty: PenaltyInfo): Promise<void> {
    this.penalties.set(key, penalty);
  }
  
  async deletePenalty(key: string): Promise<void> {
    this.penalties.delete(key);
  }
}

5. Rate Limiting Monitoring

// Rate limiting monitoring and alerting
interface RateLimitMetrics {
  totalRequests: number;
  blockedRequests: number;
  blockedByRule: Record<string, number>;
  averageResponseTime: number;
  topViolators: ViolatorInfo[];
}

interface ViolatorInfo {
  key: string;
  violations: number;
  lastViolation: number;
  rule: string;
}

class RateLimitMonitor {
  private metrics: RateLimitMetrics = {
    totalRequests: 0,
    blockedRequests: 0,
    blockedByRule: {},
    averageResponseTime: 0,
    topViolators: []
  };
  
  private responseTimes: number[] = [];
  private violators = new Map<string, ViolatorInfo>();
  
  recordRequest(blocked: boolean, rule?: string, key?: string, responseTime?: number): void {
    this.metrics.totalRequests++;
    
    if (blocked) {
      this.metrics.blockedRequests++;
      
      if (rule) {
        this.metrics.blockedByRule[rule] = (this.metrics.blockedByRule[rule] || 0) + 1;
      }
      
      if (key) {
        this.updateViolator(key, rule);
      }
    }
    
    if (responseTime) {
      this.responseTimes.push(responseTime);
      if (this.responseTimes.length > 1000) {
        this.responseTimes.shift();
      }
      this.metrics.averageResponseTime = this.responseTimes.reduce((sum, time) => sum + time, 0) / this.responseTimes.length;
    }
  }
  
  private updateViolator(key: string, rule: string): void {
    const existing = this.violators.get(key);
    
    if (existing) {
      existing.violations++;
      existing.lastViolation = Date.now();
    } else {
      this.violators.set(key, {
        key,
        violations: 1,
        lastViolation: Date.now(),
        rule
      });
    }
    
    // Update top violators
    this.metrics.topViolators = Array.from(this.violators.values())
      .sort((a, b) => b.violations - a.violations)
      .slice(0, 10);
  }
  
  getMetrics(): RateLimitMetrics {
    return { ...this.metrics };
  }
  
  getAlerts(): RateLimitAlert[] {
    const alerts: RateLimitAlert[] = [];
    
    // High block rate alert
    const blockRate = this.metrics.blockedRequests / this.metrics.totalRequests;
    if (blockRate > 0.1) { // More than 10% blocked
      alerts.push({
        type: 'high_block_rate',
        severity: 'warning',
        message: `High block rate: ${(blockRate * 100).toFixed(2)}%`,
        value: blockRate,
        threshold: 0.1
      });
    }
    
    // Top violator alert
    const topViolator = this.metrics.topViolators[0];
    if (topViolator && topViolator.violations > 100) {
      alerts.push({
        type: 'excessive_violations',
        severity: 'warning',
        message: `Excessive violations from ${topViolator.key}: ${topViolator.violations}`,
        value: topViolator.violations,
        threshold: 100
      });
    }
    
    // Response time alert
    if (this.metrics.averageResponseTime > 100) { // More than 100ms
      alerts.push({
        type: 'high_response_time',
        severity: 'warning',
        message: `High average response time: ${this.metrics.averageResponseTime.toFixed(2)}ms`,
        value: this.metrics.averageResponseTime,
        threshold: 100
      });
    }
    
    return alerts;
  }
  
  reset(): void {
    this.metrics = {
      totalRequests: 0,
      blockedRequests: 0,
      blockedByRule: {},
      averageResponseTime: 0,
      topViolators: []
    };
    this.responseTimes = [];
    this.violators.clear();
  }
}

interface RateLimitAlert {
  type: string;
  severity: 'info' | 'warning' | 'error';
  message: string;
  value: number;
  threshold: number;
}

Integration Patterns

API Department Integration

  • Endpoint protection and throttling
  • User-based rate limiting
  • API abuse prevention

Security Department Integration

  • DDoS protection coordination
  • Abuse detection and response
  • Security monitoring integration

Monitoring Integration

  • Rate limiting metrics collection
  • Alert generation and notification
  • Performance monitoring

Stop Conditions

STOP rate limiting operations and escalate if:

  • Rate limiting system failures
  • Storage mechanism failures
  • High false positive rates
  • Performance degradation
  • Legitimate users blocked

PAUSE operations if:

  • Rate limiting configuration changes
  • Storage system maintenance
  • High traffic periods
  • Monitoring system issues

Best Practices

Rate Limiting Strategy:

  • Multiple algorithms for different use cases
  • Hierarchical limiting (global → user → endpoint)
  • Graceful degradation and fail-open
  • Clear communication to users

Configuration Management:

  • Environment-specific limits
  • Dynamic limit adjustment
  • A/​B testing of limits
  • Business rule alignment

Monitoring and Alerting:

  • Comprehensive metrics collection
  • Real-time alerting
  • Performance impact monitoring
  • User experience tracking