agentsclimarketplace

Rate limiting patterns

Skill goharabbas321/zeoel-framework/all-skills/rate-limiting-patterns

23-agent AI development team for Claude Code, Cursor, and Gemini CLI. Multi-agent orchestration framework with strict TDD, sprint planning, 420+ skills, and automated QA/security/SEO audits. Stop vibe-coding — start shipping production-grade software.

Install
npx -y skills add goharabbas321/zeoel-framework --skill rate-limiting-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

API rate limiting and throttling patterns. Covers token bucket, sliding window, Redis-based limiters, tiered limits, and DDoS protection strategies.

SKILL.md

4.1 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it

Rate Limiting Patterns

Overview

Rate limiting protects your API from abuse, ensures fair usage, and prevents cascading failures. This skill covers algorithm selection, implementation patterns, and tiered limiting for SaaS applications.

When to Use

  • Protecting public APIs from abuse
  • Implementing fair-use policies for SaaS tiers (free vs. pro vs. enterprise)
  • Preventing DDoS and brute-force attacks
  • Rate limiting webhook deliveries or email sends

Algorithms

Token Bucket (Recommended)

// Redis-based token bucket
import Redis from 'ioredis'
const redis = new Redis()

async function tokenBucket(key: string, maxTokens: number, refillRate: number): Promise<boolean> {
  const now = Date.now()
  const script = `
    local key = KEYS[1]
    local maxTokens = tonumber(ARGV[1])
    local refillRate = tonumber(ARGV[2])
    local now = tonumber(ARGV[3])

    local data = redis.call('HMGET', key, 'tokens', 'lastRefill')
    local tokens = tonumber(data[1]) or maxTokens
    local lastRefill = tonumber(data[2]) or now

    -- Refill tokens
    local elapsed = (now - lastRefill) / 1000
    tokens = math.min(maxTokens, tokens + elapsed * refillRate)

    if tokens >= 1 then
      tokens = tokens - 1
      redis.call('HMSET', key, 'tokens', tokens, 'lastRefill', now)
      redis.call('EXPIRE', key, 3600)
      return 1
    else
      redis.call('HMSET', key, 'tokens', tokens, 'lastRefill', now)
      redis.call('EXPIRE', key, 3600)
      return 0
    end
  `
  const allowed = await redis.eval(script, 1, key, maxTokens, refillRate, now)
  return allowed === 1
}

Sliding Window

async function slidingWindow(key: string, limit: number, windowMs: number): Promise<boolean> {
  const now = Date.now()
  const windowStart = now - windowMs

  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 entries in window
  pipeline.expire(key, Math.ceil(windowMs / 1000))

  const results = await pipeline.exec()
  const count = results![2][1] as number
  
  if (count > limit) {
    // Remove the entry we just added
    await redis.zremrangebyscore(key, now, now)
    return false
  }
  return true
}

Express Middleware

import rateLimit from 'express-rate-limit'
import RedisStore from 'rate-limit-redis'

// Tiered rate limiting for SaaS
const createLimiter = (tier: 'free' | 'pro' | 'enterprise') => {
  const limits = { free: 100, pro: 1000, enterprise: 10000 }
  return rateLimit({
    windowMs: 60 * 1000, // 1 minute
    max: limits[tier],
    standardHeaders: 'draft-7',
    legacyHeaders: false,
    store: new RedisStore({ sendCommand: (...args) => redis.call(...args) }),
    keyGenerator: (req) => req.user?.id || req.ip,
    handler: (req, res) => {
      res.status(429).json({
        error: 'Too many requests',
        retryAfter: res.getHeader('Retry-After'),
      })
    },
  })
}

Response Headers (RFC 6585 / draft-7)

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

Guidelines

  1. Use Token Bucket for most APIs — it allows bursts while maintaining average rate
  2. Use Redis for distributed rate limiting across multiple servers
  3. Set Retry-After header on 429 responses
  4. Tier your limits by plan (free/pro/enterprise) and endpoint sensitivity
  5. Rate limit by user ID (authenticated) or IP (unauthenticated)
  6. Apply stricter limits to auth endpoints (login, password reset)

Anti-Patterns

  • ❌ In-memory rate limiting in multi-server deployments (not shared)
  • ❌ Not returning Retry-After header on 429 responses
  • ❌ Same rate limit for all endpoints (auth endpoints need stricter limits)
  • ❌ Rate limiting only by IP (shared IPs, NAT, proxies)
  • ❌ Not whitelisting health check endpoints from rate limiting

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.