Skip to main content

Rate Limiting & DDoS — Controlling Request Volume

Rate limiting caps per-client request rate. DDoS protection absorbs volumetric attacks at the CDN/network edge before they reach your origin.

When to use

  • All public APIs; especially login, signup, payment endpoints
  • Token bucket for API rate limits; CDN-level DDoS protection for volumetric attacks

Tradeoffs

  • Too aggressive blocks legitimate traffic (especially behind NAT — many users same IP)
  • Shared counters need distributed state (Redis atomic operations)
// Token bucket via Redis atomic operations
func Allow(ctx context.Context, rdb *redis.Client, key string, burst, rate int) (bool, error) {
now := time.Now().Unix()
pipe := rdb.Pipeline()
// refill tokens proportional to elapsed time
pipe.SetNX(ctx, key+":ts", now, 24*time.Hour)
pipe.SetNX(ctx, key+":tokens", burst, 24*time.Hour)
pipe.Exec(ctx)

tokens, err := rdb.DecrBy(ctx, key+":tokens", 1).Result()
if err != nil {
return false, err
}
if tokens < 0 {
rdb.IncrBy(ctx, key+":tokens", 1) // restore
return false, nil // 429
}
return true, nil
}

Gotcha: Rate limit by authenticated user ID AND by IP AND by endpoint. A single user hammering one endpoint should not trigger a global block for all users on that IP.