ratelimit

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: MIT Imports: 16 Imported by: 10

Documentation

Overview

Package ratelimit implements the platform-wide, Redis-backed, per-client, per-route-tier request rate limiter for sweetrpg Go HTTP services. Counters live in Redis (INCR + EXPIRE) rather than per-pod memory, so a client's limit is consistent across a service's replicas instead of being N times looser depending on how many pods are up.

If the counter store is unreachable, standard-tier routes fail closed (503) rather than being served as if unlimited, while /status/* routes fail open so a cache fault cannot fail the liveness and readiness probes that call them (PADR-0036). Every store error is logged at ERROR and counted in ratelimit_backend_errors_total{tier}. Every 429 carries a Retry-After header.

Index

Constants

View Source
const (
	TierCheap    = "cheap"
	TierStandard = "standard"
)

Tier names. Routes under /status/ use the looser cheap tier; everything else uses standard.

Variables

This section is empty.

Functions

func ClientKey

func ClientKey(c *gin.Context) string

ClientKey identifies the caller for per-client limiting: the API key if the client sent an X-API-Key header, otherwise the client IP. It does not introduce an auth mechanism - it keys off whatever identity already exists on the request. The key:/ip: prefixes keep a client that sends an API key and one that does not from colliding on the same source address.

func Middleware

func Middleware(pool *redis.Pool, opts Options) gin.HandlerFunc

Middleware returns a gin handler that enforces per-client, per-tier limits backed by the given Redis pool. It aborts with 429 (ErrorRateLimited, plus Retry-After) when a client is over its tier limit. When the pool is nil or the store errors it logs, counts, and then either lets the request through (/status/*, so probes survive a cache fault) or aborts with 503 (ErrorRateLimitUnavailable) for every other route.

func Ping

func Ping(ctx context.Context, pool *redis.Pool) error

Ping verifies the Redis backend is reachable, for use in startup/readiness checks.

func TierFor

func TierFor(path string) string

TierFor groups routes into the cheap tier (shallow /status endpoints) and the standard tier (everything else), keyed by route cost rather than one entry per resource.

Types

type Limiter

type Limiter struct {
	// contains filtered or unexported fields
}

Limiter enforces per-client request limits per tier, backed by a Redis connection pool.

func New

func New(pool *redis.Pool, tiers map[string]Tier) *Limiter

New builds a Limiter using the given Redis pool and tier definitions. Callers should pass at least a "standard" and "cheap" tier; Allow falls back to "standard" for an unknown tier name.

func (*Limiter) Allow

func (l *Limiter) Allow(ctx context.Context, clientKey, tierName string) (bool, error)

Allow increments the request counter for clientKey within the named tier and reports whether the request is within that tier's limit. A non-nil error means the Redis backend was unreachable; Middleware decides per tier whether that fails open or closed.

func (*Limiter) Check added in v0.4.0

func (l *Limiter) Check(ctx context.Context, clientKey, tierName string) (Result, error)

Check is Allow plus, for a rejected request, how long the client should wait.

type Options

type Options struct {
	Cheap    Tier
	Standard Tier
}

Options configures the middleware's tier budgets.

func DefaultOptions

func DefaultOptions() Options

DefaultOptions reads the tier budgets from the standard env vars (RATE_LIMIT_CHEAP / RATE_LIMIT_CHEAP_WINDOW_SECONDS / RATE_LIMIT_STANDARD / RATE_LIMIT_STANDARD_WINDOW_SECONDS), falling back to the catalog-api-validated defaults.

type Result added in v0.4.0

type Result struct {
	Allowed    bool
	RetryAfter time.Duration
}

Result is the outcome of one limit check. RetryAfter is how long until the client's window resets; it is only meaningful when Allowed is false, and is at least one second.

type Tier

type Tier struct {
	Limit  int
	Window int
}

Tier describes a rate-limit budget: at most Limit requests per Window seconds.

Jump to

Keyboard shortcuts

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