ratelimiter

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 18, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

README

ratelimiter

Package ratelimiter provides a distributed, Redis-backed fixed-window rate limiter used by the Aibrix gateway to enforce per-user and per-model request limits across multiple gateway instances.

Interface

type RateLimiter interface {
    Get(ctx context.Context, key string) (int64, error)
    GetLimit(ctx context.Context, key string) (int64, error)
    Incr(ctx context.Context, key string, val int64) (int64, error)
}
Method Description
Get Returns the current counter value for a key in the active time window.
GetLimit Returns the configured maximum for a key (used for limit lookups, not window counters).
Incr Atomically increments the counter by val and returns the new value. Sets the key TTL to the window size.

Implementations

redisRateLimiterNewRedisAccountRateLimiter(name, client, windowSize)

A fixed-window counter backed by Redis. Suitable for cluster-wide enforcement when multiple gateway replicas share the same Redis instance.

Key scheme: {name}:{key}:{timebin}

The time bin is computed as:

timebin = (time.Now().Unix() / windowSeconds) % 64

This cycles through 64 buckets, so at most 64 keys exist per logical counter. The TTL on each key is set to windowSize, so stale bins expire automatically.

  • Minimum windowSize is 1 second (smaller values are clamped up).
  • Incr uses a Redis pipeline (INCRBY + EXPIRE) for atomicity within a single round-trip.
  • A missing key (redis.Nil) is treated as 0, not an error.
noopRateLimiterNewNoopRateLimiter()

A no-op implementation that always allows requests. Used when Redis is unavailable (e.g., local development without a Redis sidecar). GetLimit returns math.MaxInt64.

Usage in the gateway

Two limiter instances are created at server startup:

Instance Constructor arg name windowSize Purpose
ratelimiter "aibrix" 1 minute Per-user RPM and TPM enforcement
modelRateLimiter "aibrix_model" 1 second Per-model RPS enforcement

The separate name prefix ensures the two limiters' keys never collide in Redis.

Per-user limits (RPM / TPM)

Keys follow the pattern aibrix:{username}_{RPM|TPM}_CURRENT:{timebin}. Limits are read from the user record resolved during request header processing.

Per-model RPS

Keys follow the pattern aibrix_model:{modelName}_MODEL_RPS_CURRENT:{timebin}. The RPS limit is configured per model via the requestsPerSecond field in a config profile:

{
  "profiles": {
    "rps-limited": {
      "routingStrategy": "least-request",
      "requestsPerSecond": 1
    }
  }
}

The active profile is selected by passing the config-profile request header. If no profile is active or requestsPerSecond is unset, the RPS check is skipped entirely.

Enforcement flow

Per-model RPS enforcement is handled in HandleRequestBody via enforceModelRPS and a deferred compensation step:

  1. Pre-routing gate (enforceModelRPS) — called before routing. It:
    • atomically increments the counter with Incr(..., +1) and receives the new value
    • rejects with HTTP 429 and rolls back with Incr(..., -1) if newVal > limit
    • allows the request through when newVal <= limit
  2. Deferred compensation (decrModelRPS) — armed immediately after a successful pre-charge. If routing later fails, the deferred call refunds quota with Incr(..., -1).
  3. Success path — after routing succeeds and request accounting is attached, compensation is disabled, so the pre-charge remains counted.

Using incr-then-check (rather than check-then-increment) means the INCRBY is the sole gate. Because Redis processes INCRBY atomically, each concurrent caller receives a unique sequential result — eliminating the TOCTOU race that would otherwise allow over-admission during the check→increment window.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type RateLimiter

type RateLimiter interface {
	// Get retrieves the current rate limit usage for the given key.
	// Returns the current value of the rate limit counter and an error if retrieval fails.
	Get(ctx context.Context, key string) (int64, error)

	// GetLimit retrieves the configured maximum rate limit for the given key.
	// Returns the maximum allowed value for the rate limit and an error if retrieval fails.
	GetLimit(ctx context.Context, key string) (int64, error)

	// Incr increments the rate limit counter for the given key by the specified value.
	// Returns the updated rate limit counter after the increment and an error if the operation fails.
	Incr(ctx context.Context, key string, val int64) (int64, error)
}

RateLimiter defines an interface for rate limiting operations. It allows querying, retrieving limits, and incrementing usage for a given key.

func NewNoopRateLimiter added in v0.7.0

func NewNoopRateLimiter() RateLimiter

func NewRedisAccountRateLimiter

func NewRedisAccountRateLimiter(name string, client *redis.Client, windowSize time.Duration) RateLimiter

NewRedisAccountRateLimiter is a simple fixed window rate limiter

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL