Created
March 14, 2026 15:12
-
-
Save mohashari/f0c0c3b38566b065ca18da12396ca870 to your computer and use it in GitHub Desktop.
Code snippets — System Design Rate Limiting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func (rl *SlidingWindowLogLimiter) Allow(key string, userID string) bool { | |
| now := time.Now().UnixMilli() | |
| windowStart := now - rl.windowMs | |
| pipe := redis.Pipeline() | |
| // Remove old entries | |
| pipe.ZRemRangeByScore(ctx, key, "0", strconv.FormatInt(windowStart, 10)) | |
| // Count current window | |
| countCmd := pipe.ZCard(ctx, key) | |
| // Add current request | |
| pipe.ZAdd(ctx, key, redis.Z{Score: float64(now), Member: now}) | |
| pipe.Expire(ctx, key, time.Duration(rl.windowMs)*time.Millisecond) | |
| pipe.Exec(ctx) | |
| return countCmd.Val() < rl.limit | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Current window count + Previous window count × (overlap ratio) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func (rl *SlidingWindowCounter) Allow(key string) bool { | |
| now := time.Now() | |
| currentWindow := now.Unix() / int64(rl.windowSec) | |
| prevWindow := currentWindow - 1 | |
| currentKey := fmt.Sprintf("%s:%d", key, currentWindow) | |
| prevKey := fmt.Sprintf("%s:%d", key, prevWindow) | |
| pipe := redis.Pipeline() | |
| currentCmd := pipe.Get(ctx, currentKey) | |
| prevCmd := pipe.Get(ctx, prevKey) | |
| pipe.Exec(ctx) | |
| currentCount, _ := strconv.ParseFloat(currentCmd.Val(), 64) | |
| prevCount, _ := strconv.ParseFloat(prevCmd.Val(), 64) | |
| // How far into the current window are we? (0.0 to 1.0) | |
| windowProgress := float64(now.Unix()%int64(rl.windowSec)) / float64(rl.windowSec) | |
| // Weighted count | |
| estimatedCount := currentCount + prevCount*(1-windowProgress) | |
| if estimatedCount >= float64(rl.limit) { | |
| return false | |
| } | |
| // Increment current window | |
| redis.Incr(ctx, currentKey) | |
| redis.Expire(ctx, currentKey, time.Duration(rl.windowSec*2)*time.Second) | |
| return true | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Rate: 10 tokens/second, Capacity: 100 tokens | |
| - Quiet period → bucket fills to 100 | |
| - Burst → user can fire 100 requests instantly | |
| - Steady state → 10 requests/second sustained |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type TokenBucket struct { | |
| rate float64 // tokens per second | |
| capacity float64 | |
| tokens float64 | |
| lastTime time.Time | |
| mu sync.Mutex | |
| } | |
| func (tb *TokenBucket) Allow() bool { | |
| tb.mu.Lock() | |
| defer tb.mu.Unlock() | |
| now := time.Now() | |
| elapsed := now.Sub(tb.lastTime).Seconds() | |
| tb.lastTime = now | |
| // Add tokens based on elapsed time | |
| tb.tokens = math.Min(tb.capacity, tb.tokens+elapsed*tb.rate) | |
| if tb.tokens >= 1 { | |
| tb.tokens-- | |
| return true | |
| } | |
| return false | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Incoming requests → [ Queue (max 100) ] → Process at fixed rate (10/s) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func RateLimitMiddleware(limiter Limiter) func(http.Handler) http.Handler { | |
| return func(next http.Handler) http.Handler { | |
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| // Use IP + user ID as key (or just IP for unauthenticated) | |
| key := getRateLimitKey(r) | |
| result := limiter.Allow(key) | |
| if !result.Allowed { | |
| w.Header().Set("X-RateLimit-Limit", strconv.Itoa(result.Limit)) | |
| w.Header().Set("X-RateLimit-Remaining", "0") | |
| w.Header().Set("X-RateLimit-Reset", strconv.FormatInt(result.ResetAt.Unix(), 10)) | |
| w.Header().Set("Retry-After", strconv.Itoa(int(result.RetryAfter.Seconds()))) | |
| http.Error(w, "Too Many Requests", http.StatusTooManyRequests) | |
| return | |
| } | |
| w.Header().Set("X-RateLimit-Limit", strconv.Itoa(result.Limit)) | |
| w.Header().Set("X-RateLimit-Remaining", strconv.Itoa(result.Remaining)) | |
| next.ServeHTTP(w, r) | |
| }) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func getRateLimit(userTier string) (limit int, window time.Duration) { | |
| switch userTier { | |
| case "free": | |
| return 100, time.Hour | |
| case "pro": | |
| return 1000, time.Hour | |
| case "enterprise": | |
| return 10000, time.Hour | |
| default: | |
| return 60, time.Hour // Unauthenticated | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func (rl *FixedWindowLimiter) Allow(key string) bool { | |
| now := time.Now() | |
| windowKey := fmt.Sprintf("%s:%d", key, now.Unix()/60) // 1-minute windows | |
| count, _ := redis.Incr(ctx, windowKey).Result() | |
| if count == 1 { | |
| redis.Expire(ctx, windowKey, 60*time.Second) | |
| } | |
| return count <= rl.limit | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- token_bucket.lua | |
| local key = KEYS[1] | |
| local rate = tonumber(ARGV[1]) | |
| local capacity = tonumber(ARGV[2]) | |
| local now = tonumber(ARGV[3]) | |
| local bucket = redis.call('HMGET', key, 'tokens', 'last_time') | |
| local tokens = tonumber(bucket[1]) or capacity | |
| local last_time = tonumber(bucket[2]) or now | |
| local elapsed = now - last_time | |
| tokens = math.min(capacity, tokens + elapsed * rate) | |
| if tokens >= 1 then | |
| tokens = tokens - 1 | |
| redis.call('HMSET', key, 'tokens', tokens, 'last_time', now) | |
| redis.call('EXPIRE', key, 3600) | |
| return 1 | |
| else | |
| redis.call('HMSET', key, 'tokens', tokens, 'last_time', now) | |
| return 0 | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Window: 0-59 seconds → 100 requests allowed | |
| Window: 60-119 seconds → 100 requests allowed |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment