distlimit

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2026 License: MIT Imports: 7 Imported by: 0

README

⚡ distlimit

Go Reference Release

distlimit is an ultra-high performance, distributed, pluggable rate-limiting library for Go. Engineered for microservices, high-concurrency APIs, and financial-grade applications requiring nanosecond-level execution speeds, zero memory allocation, and multi-tier failover capabilities — now with real-time observability and zero-downtime dynamic policy reloading.


🚀 Why distlimit?

Most Go rate-limiting libraries force you into a single algorithm, lock global mutexes during background cleanup, or collapse when Redis goes down. distlimit solves these architectural flaws with enterprise-grade resilience:

  • 🔌 100% Pluggable Strategy Architecture: Swap algorithms seamlessly without changing your storage driver or HTTP framework middleware.
  • ⚡ Zero Allocation & Nanosecond Latency: Memory evaluation runs in sub-100 nanoseconds with 0 B/op memory overhead across all standard algorithms.
  • 🔒 64-Sharded Memory Architecture: Eliminates global lock contention during concurrent HTTP requests and background state cleanups.
  • 🛡️ Half-Open Circuit Breaker (Hybrid Driver): Automatic failover from Redis to In-Memory with single-request probing to prevent Thundering Herd spikes upon Redis recovery.
  • 🔐 Security-First Middlewares: Built-in protection against IP Spoofing via CIDR-validated WithTrustedProxies headers inspection.
  • 🌐 Native Redis Cluster Safety: Enforces Redis Hash Tags {} to prevent CROSSSLOT cluster routing errors.
  • 📊 Pluggable Observability (v1.2.0): Zero-allocation telemetry via metrics.Observer with turnkey Prometheus & OpenTelemetry collectors.
  • 🔄 Dynamic Policy Engine (v1.2.0): Lock-free $O(1)$ runtime policy updates with atomic.Pointer[Policy] and multi-tenant tier resolution.

📐 Architecture Overview

                    +----------------------------+
                    |  HTTP / gRPC Incoming Req  |
                    +----------------------------+
                                  |
                     [ Trusted Proxies Check ]  <-- IP Spoofing Shield
                                  |
                    +----------------------------+
                    |     distlimit.Limiter      |
                    +----------------------------+
                                  |
           +----------------------+----------------------+
           |                                             |
 [ Pluggable Algorithm ]                         [ Storage Driver ]

* Token Bucket                                 - Memory (64-Sharded)
* Leaky Bucket                                 - Redis (Cluster Hash-Tagged)
* Fixed Window                                 - Hybrid (Circuit Breaker)
* Sliding Window Log
* Sliding Window Counter


🧮 Supported Algorithms

Algorithm Traffic Pattern Memory Redis Data Structure Best Use Case
Token Bucket Burst Friendly $O(1)$ Hash General-purpose API rate limiting with burst support.
Leaky Bucket Traffic Shaping $O(1)$ Hash Smoothing spikes for third-party integrations (e.g., Payment Gateways).
Fixed Window Interval Reset $O(1)$ String Counter Ultra-lightweight endpoint protection & login brute-force shielding.
Sliding Window Log 100% Exact Precision $O(N)$ Sorted Set (ZSET) Strict quota allocation, financial transactions, and zero-compromise limits.
Sliding Window Counter Weighted Moving Avg $O(1)$ Hash High-throughput distributed rate limiting with $O(1)$ memory precision.

📋 Prerequisites

  • Go: 1.20 or higher
  • Redis (Optional for distributed driver): Standalone, Sentinel, or Cluster v6.0+

📦 Installation

go get github.com/balramadan/distlimit

⚡ Quickstart

1. Basic In-Memory Limiter

Evaluate rate limits using the 64-sharded in-memory driver with Sliding Window Counter:

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/balramadan/distlimit"
	"github.com/balramadan/distlimit/algorithm/slidingcounter"
	"github.com/balramadan/distlimit/driver/memory"
)

func main() {
	// Initialize 64-Sharded Memory Driver (TTL 5 minutes)
	memDriver := memory.New(5 * time.Minute)
	defer memDriver.Close(context.Background())

	// Create Limiter: 10 requests per 1 minute using Sliding Window Counter
	limiter, err := distlimit.New(
		memDriver,
		distlimit.WithLimit(10),
		distlimit.WithWindow(1*time.Minute),
		distlimit.WithAlgorithm(slidingcounter.New()),
	)
	if err != nil {
		panic(err)
	}

	// Evaluate Rate Limit for a key
	res, err := limiter.AllowKey(context.Background(), "user:123")
	if err != nil {
		panic(err)
	}

	if res.Allowed {
		fmt.Printf("Allowed! Remaining: %d\n", res.Remaining)
	} else {
		fmt.Printf("Blocked! Retry after: %v\n", res.ResetIn)
	}
}

2. HTTP Middleware with Anti-Spoofing & Observability

Protect HTTP endpoints with trusted proxy validation, Prometheus metrics, and per-route labels — all in one setup:

package main

import (
	"net/http"
	"time"

	"github.com/balramadan/distlimit"
	"github.com/balramadan/distlimit/algorithm/tokenbucket"
	"github.com/balramadan/distlimit/driver/memory"
	distprom "github.com/balramadan/distlimit/metrics/prometheus"
	distlimitnethttp "github.com/balramadan/distlimit/middleware/nethttp"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
	memDriver := memory.New(5 * time.Minute)
	defer memDriver.Close(nil)

	// Attach Prometheus Observer
	promObserver := distprom.NewObserver(
		distprom.WithNamespace("my_app"),
		distprom.WithSubsystem("api"),
	)

	limiter, _ := distlimit.New(
		memDriver,
		distlimit.WithLimit(100),
		distlimit.WithWindow(1*time.Minute),
		distlimit.WithAlgorithm(tokenbucket.New()),
		distlimit.WithMetricObserver(promObserver),
	)

	mux := http.NewServeMux()

	// Rate-limited handler with route labeling & trusted proxy protection
	apiHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`{"status":"ok"}`))
	})
	mux.Handle("/api/v1/resource", distlimitnethttp.New(
		limiter,
		distlimitnethttp.WithTrustedProxies([]string{"10.0.0.0/8", "172.16.0.0/12"}),
		distlimitnethttp.WithRouteLabeling(true), // passes "/api/v1/resource" into metric labels
	)(apiHandler))

	// Expose Prometheus scrape endpoint
	mux.Handle("/metrics", promhttp.Handler())

	http.ListenAndServe(":8080", mux)
}

Exported Prometheus metrics:

Metric Type Description
distlimit_requests_total Counter Total evaluations by allowed, driver, algorithm, route
distlimit_evaluation_duration_seconds Histogram Execution latency of each evaluation
distlimit_hybrid_fallback_total Counter Times the Hybrid Driver failed over to memory

3. Resilient Dual-Tier Hybrid Driver (Redis + Memory Fallback)

Automatic failover to in-memory fallback with Half-Open Circuit Breaker if Redis connection drops:

package main

import (
	"context"
	"log"
	"time"

	"github.com/balramadan/distlimit"
	"github.com/balramadan/distlimit/algorithm/slidingcounter"
	distlimithybrid "github.com/balramadan/distlimit/driver/hybrid"
	distlimitmemory "github.com/balramadan/distlimit/driver/memory"
	distlimitredis "github.com/balramadan/distlimit/driver/redis"
	"github.com/redis/go-redis/v9"
)

func main() {
	rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
	primary := distlimitredis.New(rdb)
	fallback := distlimitmemory.New(5 * time.Minute)

	// Hybrid Driver with 5s Cool-Off and Half-Open Probing
	hybridDriver := distlimithybrid.New(
		primary,
		fallback,
		distlimithybrid.WithCoolOffDuration(5*time.Second),
		distlimithybrid.WithOnError(func(err error) {
			log.Printf("[DISTLIMIT WARN] Redis down, failing over to memory: %v", err)
		}),
	)

	limiter, _ := distlimit.New(
		hybridDriver,
		distlimit.WithLimit(500),
		distlimit.WithWindow(1*time.Minute),
		distlimit.WithAlgorithm(slidingcounter.New()),
	)

	_, _ = limiter.AllowKey(context.Background(), "api_key_abc")
}

4. Dynamic Policy Reloading & Multi-Tenant Tier Resolution

Update global limits at runtime without restarts, and apply per-key tier overrides via PolicyResolver:

// Lock-free O(1) runtime update — no restart, no lock contention
limiter.UpdatePolicy(500, 1*time.Minute)

// Multi-tenant PolicyResolver: VIP users get a higher quota
type TierResolver struct{}

func (r *TierResolver) ResolvePolicy(ctx context.Context, key string) (distlimit.Policy, bool) {
	if strings.HasPrefix(key, "vip:") {
		return distlimit.Policy{Limit: 5000, Window: 1 * time.Minute}, true
	}
	return distlimit.Policy{}, false // fallback to default
}

limiter, _ := distlimit.New(
	driver,
	distlimit.WithLimit(100),
	distlimit.WithWindow(1*time.Minute),
	distlimit.WithPolicyResolver(&TierResolver{}),
)

5. OpenTelemetry Instrumentation
import (
	distotel "github.com/balramadan/distlimit/metrics/otel"
	"go.opentelemetry.io/otel"
)

otelObserver := distotel.NewObserver(
	distotel.WithMeterProvider(otel.GetMeterProvider()),
)

limiter, _ := distlimit.New(
	driver,
	distlimit.WithMetricObserver(otelObserver),
)

6. Route Labeling for All Middleware Adapters

Pass the parametrized route pattern (e.g., /api/v1/users/:id) or gRPC FullMethod into metric labels automatically:

// net/http — uses r.Pattern (Go 1.22+) or fallback to r.URL.Path
distlimitnethttp.New(limiter, distlimitnethttp.WithRouteLabeling(true))

// Gin — uses c.FullPath()
distlimitgin.New(limiter, distlimitgin.WithRouteLabeling(true))

// Echo v4 — uses c.Path()
distlimitecho.New(limiter, distlimitecho.WithRouteLabeling(true))

// gRPC — uses info.FullMethod (e.g. /package.Service/Method)
grpc.NewServer(grpc.ChainUnaryInterceptor(
	distlimitgrpc.UnaryServerInterceptor(limiter, distlimitgrpc.WithRouteLabeling(true)),
))

🛡️ Framework & Middleware Adapters

distlimit provides native, zero-dependency middleware adapters for all popular Go web frameworks:

Framework Import Path Route Labeling
⚡ Fiber v3 github.com/balramadan/distlimit/middleware/fiber WithRouteLabeling(true)
🍸 Gin github.com/balramadan/distlimit/middleware/gin WithRouteLabeling(true)
🔊 Echo v4 github.com/balramadan/distlimit/middleware/echo WithRouteLabeling(true)
🔊 Echo v5 github.com/balramadan/distlimit/middleware/echov5 WithRouteLabeling(true)
🌐 Standard net/http github.com/balramadan/distlimit/middleware/nethttp WithRouteLabeling(true)
📡 gRPC github.com/balramadan/distlimit/middleware/grpc WithRouteLabeling(true)

📊 Performance & Benchmarks

Benchmarks executed on AMD 3020e Linux x86_64 (go test -bench=. -benchmem -count=1 ./algorithm/... ./...):

pkg: github.com/balramadan/distlimit/algorithm/*
cpu: AMD 3020e with Radeon Graphics

BenchmarkSlidingLog_EvaluateMemory-2        46,176,700    22.37 ns/op    0 B/op    0 allocs/op
BenchmarkTokenBucket_EvaluateMemory-2       22,270,572    49.59 ns/op    0 B/op    0 allocs/op
BenchmarkLeakyBucket_EvaluateMemory-2       23,049,756    67.77 ns/op    0 B/op    0 allocs/op
BenchmarkFixedWindow_EvaluateMemory-2       14,373,084   106.30 ns/op    0 B/op    0 allocs/op
BenchmarkSlidingCounter_EvaluateMemory-2     6,060,211   214.00 ns/op    0 B/op    0 allocs/op

-- Full Limiter Stack (driver + algorithm + policy evaluation) --
BenchmarkLimiter_NoObserver-2                  311,350   3,446.00 ns/op  0 B/op    0 allocs/op

Key Takeaway: All 5 algorithms achieve zero memory allocations (0 B/op, 0 allocs/op) during in-memory evaluation, allowing your Go application to handle tens of millions of rate-check operations per second without GC pause overhead. The full limiter stack including driver + algorithm + atomic policy evaluation also maintains 0 B/op — and so does the telemetry observer path when disabled.


📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Overview

Package distlimit provides a high-performance, resilient, and pluggable rate limiting library for Go applications. It supports pluggable algorithm strategies (Token Bucket, Leaky Bucket, Sliding Window Counter, Sliding Window Log, Fixed Window), multiple storage drivers (In-Memory, Redis, Hybrid Dual-Tier), and turn-key middleware adapters for popular frameworks.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidLimit is returned when the configured rate limit is less than or equal to 0.
	ErrInvalidLimit = errors.New("distlimit: limit must be greater than 0")

	// ErrInvalidWindow is returned when the configured rate limit window is less than or equal to 0.
	ErrInvalidWindow = errors.New("distlimit: window must be greater than 0")

	// ErrNilDriver is returned when a nil Driver is supplied during Limiter initialization.
	ErrNilDriver = errors.New("distlimit: storage driver cannot be nil")

	// ErrNilAlgorithm is returned when a nil Algorithm is supplied to WithAlgorithm.
	ErrNilAlgorithm = errors.New("distlimit: algorithm strategy cannot be nil")
)

Sentinels errors returned by distlimit.

Functions

This section is empty.

Types

type Config added in v1.1.0

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

Config holds configuration parameters used during Limiter construction.

type Driver

type Driver interface {
	// Allow evaluates rate limit rules for the specified key using the given algorithm strategy.
	Allow(ctx context.Context, key string, limit int64, window time.Duration, alg algorithm.Algorithm) (algorithm.Result, error)

	// Reset clears the rate limit state entry for the specified key in the storage driver.
	Reset(ctx context.Context, key string) error

	// Close gracefully releases any storage connections, background routines, or resources held by the driver.
	Close(ctx context.Context) error
}

Driver defines the interface that all rate limiting storage backends (Memory, Redis, Hybrid) must implement.

type KeyFunc

type KeyFunc func(ctx context.Context) string

KeyFunc defines a function signature for dynamically extracting a rate limit key from a Context.

type Limiter

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

Limiter is the central rate limiting coordinator. It combines a storage Driver, rate rules, and an algorithm strategy to evaluate incoming requests.

Limiter is thread-safe and designed for concurrent use by multiple goroutines.

func New

func New(driver Driver, opts ...Option) (*Limiter, error)

New creates and initializes a new Limiter instance with the specified storage driver and optional options. If WithAlgorithm is omitted, it defaults to the Sliding Window Counter algorithm strategy for backward compatibility. Returns an error if driver is nil, or if limit or window are invalid (<= 0).

func (*Limiter) Allow

func (l *Limiter) Allow(ctx context.Context) (Result, error)

Allow evaluates the rate limit key extracted via the configured KeyFunc against the active limits.

func (*Limiter) AllowKey

func (l *Limiter) AllowKey(ctx context.Context, key string) (Result, error)

AllowKey evaluates the rate limit for an explicitly specified key string against the active limits.

func (*Limiter) Close

func (l *Limiter) Close(ctx context.Context) error

Close gracefully closes the underlying storage driver and releases associated resources.

func (*Limiter) ResetKey added in v1.1.1

func (l *Limiter) ResetKey(ctx context.Context, key string) error

ResetKey clears the rate limit state for the specified key in the underlying storage driver.

func (*Limiter) UpdatePolicy added in v1.2.0

func (l *Limiter) UpdatePolicy(limit int64, window time.Duration)

UpdatePolicy updates the default rate limit policy atomically at runtime without lock contention.

type Option

type Option func(*Config)

Option configures functional parameters for Limiter initialization.

func WithAlgorithm added in v1.1.0

func WithAlgorithm(alg algorithm.Algorithm) Option

WithAlgorithm sets the pluggable rate limiting algorithm strategy (e.g., tokenbucket, leakybucket, slidingcounter).

func WithKeyFunc

func WithKeyFunc(fn KeyFunc) Option

WithKeyFunc configures a custom key extraction function for extracting rate limit keys from context.

func WithLimit

func WithLimit(limit int64) Option

WithLimit sets the maximum number of requests allowed within the configured time window.

func WithMetricObserver added in v1.2.0

func WithMetricObserver(obs metrics.Observer) Option

WithMetricObserver sets a custom telemetry/metrics observer for recording evaluation events.

func WithPolicyResolver added in v1.2.0

func WithPolicyResolver(resolver PolicyResolver) Option

WithPolicyResolver sets a dynamic policy resolver for evaluating tier-based rate limits per key.

func WithWindow

func WithWindow(window time.Duration) Option

WithWindow sets the duration of the rate limiting time window.

type Policy added in v1.2.0

type Policy struct {
	// Limit is the maximum number of requests allowed within the Window duration.
	Limit int64
	// Window is the time duration of the rate limit window.
	Window time.Duration
}

Policy defines the rate limit capacity rules (Limit and Window duration).

type PolicyResolver added in v1.2.0

type PolicyResolver interface {
	// ResolvePolicy returns a dynamic Policy for the specified key.
	// If false is returned, the default Limiter policy will be used.
	ResolvePolicy(ctx context.Context, key string) (Policy, bool)
}

PolicyResolver defines an interface for dynamically resolving rate limit policies per key or user tier.

type Result

type Result = algorithm.Result

Result is a type alias for algorithm.Result for backward compatibility with v1.0.0.

type State added in v1.1.0

type State = algorithm.State

State is a type alias for algorithm.State for backward compatibility with v1.0.0.

Directories

Path Synopsis
Package algorithm defines core interfaces and shared data structures for rate limiting algorithm strategies.
Package algorithm defines core interfaces and shared data structures for rate limiting algorithm strategies.
fixedwindow
Package fixedwindow implements the Fixed Window rate limiting algorithm.
Package fixedwindow implements the Fixed Window rate limiting algorithm.
leakybucket
Package leakybucket implements the Leaky Bucket rate limiting algorithm for traffic shaping.
Package leakybucket implements the Leaky Bucket rate limiting algorithm for traffic shaping.
slidingcounter
Package slidingcounter implements the Sliding Window Counter rate limiting algorithm.
Package slidingcounter implements the Sliding Window Counter rate limiting algorithm.
slidinglog
Package slidinglog implements the Sliding Window Log rate limiting algorithm.
Package slidinglog implements the Sliding Window Log rate limiting algorithm.
tokenbucket
Package tokenbucket implements the Token Bucket rate limiting algorithm.
Package tokenbucket implements the Token Bucket rate limiting algorithm.
driver
hybrid
Package hybrid implements a dual-tier resilient rate limiting driver with a Half-Open Circuit Breaker.
Package hybrid implements a dual-tier resilient rate limiting driver with a Half-Open Circuit Breaker.
memory
Package memory implements a fast, thread-safe, sharded in-memory rate limiting driver.
Package memory implements a fast, thread-safe, sharded in-memory rate limiting driver.
redis
Package redis implements a distributed rate limiting driver using Redis as the backend.
Package redis implements a distributed rate limiting driver using Redis as the backend.
examples
dynamic-policy command
echo command
echov5 command
gin-hybrid command
grpc command
nethttp command
Package metrics provides observability interfaces and telemetry data structures for distlimit.
Package metrics provides observability interfaces and telemetry data structures for distlimit.
otel
Package otel provides an OpenTelemetry metrics observer implementation for distlimit.
Package otel provides an OpenTelemetry metrics observer implementation for distlimit.
prometheus
Package prometheus provides a Prometheus metrics observer implementation for distlimit.
Package prometheus provides a Prometheus metrics observer implementation for distlimit.
middleware
echo
Package echo provides rate limiting middleware for the Echo v4 web framework.
Package echo provides rate limiting middleware for the Echo v4 web framework.
echov5
Package echov5 provides rate limiting middleware for the Echo v5 web framework.
Package echov5 provides rate limiting middleware for the Echo v5 web framework.
fiber
Package fiber provides rate limiting middleware for the Fiber v3 web framework.
Package fiber provides rate limiting middleware for the Fiber v3 web framework.
gin
Package gin provides rate limiting middleware for the Gin web framework.
Package gin provides rate limiting middleware for the Gin web framework.
grpc
Package grpc provides gRPC server interceptor middleware for rate limiting.
Package grpc provides gRPC server interceptor middleware for rate limiting.
nethttp
Package nethttp provides rate limiting middleware for Go's standard net/http package.
Package nethttp provides rate limiting middleware for Go's standard net/http package.

Jump to

Keyboard shortcuts

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