Documentation
¶
Overview ¶
Package ratelimit provides rate limiting for gRPC services.
Two implementations are available:
- Token bucket (in-memory): per-key rate limiting with burst support
- Redis sliding window (distributed): cross-instance rate limiting
The Redis implementation uses a RedisClient interface, allowing any Redis client library (go-redis, redigo, etc.) to be used.
Example:
limiter := ratelimit.NewTokenBucket(ratelimit.TokenBucketConfig{
Rate: 100,
BurstSize: 10,
})
if err := limiter.Allow(ctx, key); err != nil {
return status.Error(codes.ResourceExhausted, "rate limited")
}
Package ratelimit provides rate limiting for gRPC execution pipelines.
Architecture follows the ports-and-adapters pattern:
- Limiter is the port (interface) that any rate limiting backend must satisfy
- TokenBucket is the built-in in-memory adapter (no external dependencies)
- RedisSlidingWindow is the distributed adapter using any Redis client
In-Memory (Token Bucket):
limiter := ratelimit.NewTokenBucket(ratelimit.Config{
Rate: 100, // 100 requests
Interval: time.Second, // per second
Burst: 150, // burst up to 150
})
Redis (Sliding Window):
// rdb implements ratelimit.RedisClient (e.g., go-redis v9)
limiter := ratelimit.NewRedisSlidingWindow(rdb, ratelimit.Config{
Rate: 1000,
Interval: time.Minute,
})
Integration with GRIP pipelines:
u := unary.New(unary.WithRateLimiter(limiter))
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrRateLimited = irl.ErrRateLimited
ErrRateLimited indicates a request was rejected due to rate limiting.
var IsRateLimited = irl.IsRateLimited
IsRateLimited checks whether err is a rate-limiting rejection.
var WithKeyPrefix = irl.WithKeyPrefix
WithKeyPrefix sets a prefix for all Redis keys used by the limiter. Default: "grip:rl:"
Functions ¶
This section is empty.
Types ¶
type Config ¶
Config defines the rate limiting parameters.
Config{Rate: 100, Interval: time.Second} → 100 req/s
Config{Rate: 1000, Interval: time.Minute} → 1000 req/min
Config{Rate: 10, Burst: 50} → 10 req/s, burst to 50
type Limiter ¶
Limiter is the port that all rate limiting backends must implement.
Contract:
- Allow returns nil if the request is permitted
- Allow returns ErrRateLimited if rejected
- MUST be goroutine-safe
- MUST NOT block indefinitely
- MUST respect context cancellation
type RedisClient ¶
type RedisClient = irl.RedisClient
RedisClient is the port that any Redis client library must implement to be used as a distributed rate limiting backend.
This is deliberately minimal — only Eval is required, which every Redis client library provides (go-redis, redigo, radix, etc.).
type RedisSlidingWindow ¶
type RedisSlidingWindow = irl.RedisSlidingWindow
RedisSlidingWindow is a distributed rate limiter using Redis sorted sets. Suitable for multi-instance deployments sharing a Redis cluster.
func NewRedisSlidingWindow ¶
func NewRedisSlidingWindow(client RedisClient, cfg Config, opts ...RedisSlidingWindowOption) *RedisSlidingWindow
NewRedisSlidingWindow creates a Redis-backed sliding window rate limiter.
limiter := ratelimit.NewRedisSlidingWindow(redisClient, ratelimit.Config{
Rate: 1000,
Interval: time.Minute,
})
type RedisSlidingWindowOption ¶
type RedisSlidingWindowOption = irl.RedisSlidingWindowOption
RedisSlidingWindowOption configures the Redis sliding window limiter.
type TokenBucket ¶
type TokenBucket = irl.TokenBucket
TokenBucket is an in-memory rate limiter using the token bucket algorithm. Suitable for single-instance deployments or per-node rate limiting.
func NewTokenBucket ¶
func NewTokenBucket(cfg Config) *TokenBucket
NewTokenBucket creates an in-memory token bucket rate limiter.
limiter := ratelimit.NewTokenBucket(ratelimit.Config{
Rate: 100,
Interval: time.Second,
Burst: 150,
})