Help us shape the future of Go! Take the 2026 Go Developer Survey

ratelimit

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2026 License: MIT Imports: 10 Imported by: 0

README

Rate limiting

Limiter.Allow atomically admits and charges an operation. Limit allows Burst immediate operations and replenishes Rate admissions per Period. Redis uses redis_rate's GCRA algorithm, shared across replicas with automatic key expiry. This is gradual replenishment, not fixed windows.

limiter, err := ratelimit.NewRedis(redisClient, "my-app")
// Handle err. The caller owns redisClient and closes it after its users stop.
decision, err := limiter.Allow(ctx, "operation:opaque-account-key", ratelimit.Limit{
    Rate: 10, Burst: 10, Period: time.Hour,
})
// On error, do not proceed. On denial, decision.RetryAfter gives the wait.

Keep credentials and raw personal information out of keys. Hash account identifiers with a keyed digest. Use consistent namespaces and policies across replicas. Independent checks can conservatively consume a budget before a later check denies. A database rollback does not refund admission. Redis data loss resets budgets; configure persistence, capacity and eviction accordingly, separately from cache cleanup.

Run real Redis tests with RATE_LIMIT_TEST_REDIS=redis://localhost:6379/2. Tests use isolated namespaces and never flush a database.

Telemetry

WithTelemetry(limiter, tracerProvider, meterProvider) optionally observes every admission call. App installs it once for the shared limiter when tracing or metrics are enabled, covering both API and Identity policies. It borrows all dependencies.

ratelimit.decisions counts calls; ratelimit.duration records seconds. Their only label is outcome: allowed, denied, error, canceled, or timeout. error means the limiter returned an unclassified failure (including a backend failure), not a policy rejection. Trace spans use the same categories. Keys, policy values, and underlying error messages are never recorded. Decisions, retry delays and error identity pass through unchanged; instrumentation does not retry calls.

Documentation

Overview

Package ratelimit provides transport-independent admission limits.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Decision

type Decision struct {
	Allowed    bool
	RetryAfter time.Duration
}

type Limit

type Limit struct {
	Rate   int
	Burst  int
	Period time.Duration
}

Limit allows a burst and replenishes Rate admissions per Period.

func (Limit) Validate

func (l Limit) Validate() error

type Limiter

type Limiter interface {
	Allow(context.Context, string, Limit) (Decision, error)
}

Limiter must atomically decide and charge an admission across callers. An error is not permission to proceed. Implementations must support concurrent use.

func WithTelemetry

func WithTelemetry(next Limiter, traces trace.TracerProvider, meters metric.MeterProvider) (Limiter, error)

WithTelemetry observes decisions without recording keys, policy values or error messages. It borrows next and the providers; it does not own their lifecycle. Install once during construction. Returned errors and decisions are unchanged.

type Redis

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

Redis uses redis_rate's atomic GCRA algorithm and automatic expiry. The client is borrowed. Namespace isolates budgets from other apps and ordinary cache keys.

func NewRedis

func NewRedis(client redis.UniversalClient, namespace string) (*Redis, error)

func (*Redis) Allow

func (r *Redis) Allow(ctx context.Context, key string, limit Limit) (Decision, error)

Jump to

Keyboard shortcuts

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