Implementing Rate Limiting

1. Understanding Rate Limit Strategies

AlgorithmDetail
Fixed windowN requests / minute
Sliding windowSmoother, more accurate
Token bucketAllows bursts up to bucket size
Leaky bucketConstant outflow rate

2. Implementing IP-based Limits

PatternDetail
Anonymous trafficDefault key when no user
CDN forwardedUse CF-Connecting-IP / X-Forwarded-For
IPv6Hash /64 prefix to avoid abuse

3. Implementing User-based Limits

Example: User rate limit

const limiter = new RateLimiterRedis({
  storeClient: redis,
  keyPrefix: "user_rl",
  points: 100,
  duration: 60
});

context: async ({ req }) => {
  const user = await auth(req);
  await limiter.consume(user?.id ?? req.ip);
  return { user };
}

4. Implementing Query Complexity Limits

ApproachDetail
Per-query capReject queries above cost threshold
Cost budgetN cost units per minute per user
Cost-aware billingTier limits by plan

5. Using Rate Limit Headers

HeaderDetail
X-RateLimit-LimitMax in window
X-RateLimit-RemainingTokens left
X-RateLimit-ResetUnix time of reset
Retry-AfterSeconds to wait (on 429)

6. Implementing Throttling

PatternDetail
Queue + delaySlow down rather than reject
Concurrency capMax N in-flight per user
Tier-basedFree vs paid limits

7. Whitelisting Queries

PatternDetail
Persisted query allowlistReject any non-allowlisted query
Deploy-timeBuild allowlist from client codegen
Block introspectionDisable in production

8. Handling Rate Limit Errors

Example: Throw rate-limit error

throw new GraphQLError("Rate limit exceeded", {
  extensions: { code: "RATE_LIMITED", http: { status: 429, headers: { "Retry-After": "30" } } }
});

9. Using Redis for Rate Limiting

LibraryDetail
rate-limiter-flexibleMultiple algorithms, Redis backend
@upstash/ratelimitEdge-friendly
Lua scriptAtomic INCR + EXPIRE

10. Implementing Burst Limits

SettingDetail
Sustained ratee.g. 60/min
Burst capacityBucket size, e.g. 30 in 10 s
Refill rateTokens added per second