redis_rate

Redis-backed rate limiting for Go using the GCRA leaky-bucket algorithm.

Library
Go
vv10.0.1
1,044stars
BSD-2-Clause

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
50/100Fair
Development Activity48
Maintenance0
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
67/100Good
Architecture72
Code Quality62
Innovation78
Learning Curve55

redis_rate is a Go library that implements distributed rate limiting on top of Redis, using the GCRA (Generic Cell Rate Algorithm, aka leaky bucket) to enforce per-second, per-minute, or custom-period limits across any number of application instances. It ports the widely-used redis-gcra Lua script into a small, dependency-light Go API built directly on go-redis/v9.

Because the algorithm runs as a single atomic Lua script inside Redis, every AllowN or AllowAtMost call is race-free even under concurrent access from multiple processes, making it a common building block for API gateways, per-user quota enforcement, and login-attempt throttling.

What You Get

  • A Limiter type built on any go-redis v9 client (single node, cluster, or ring) with no extra infrastructure beyond Redis itself
  • PerSecond, PerMinute, and PerHour helpers for defining common limits, plus a raw Limit struct for custom rate/burst/period combinations
  • AllowN and AllowAtMost methods for atomic, race-free limit checks backed by a single Lua script executed inside Redis
  • A Reset method to clear a key’s rate-limit state on demand, and a Result struct exposing Allowed, Remaining, RetryAfter, and ResetAfter for building 429 responses and Retry-After headers

Common Use Cases

  • Rate-limiting API endpoints per user, API key, or IP address across a horizontally-scaled service
  • Throttling login attempts to slow down credential-stuffing and brute-force attacks
  • Enforcing per-tenant quotas in a multi-tenant SaaS backend
  • Smoothing bursty background job or webhook processing against a fixed throughput budget

Under The Hood

Architecture The library is a single small package (redis_rate) split across two files: rate.go, which defines the public API (Limit, Limiter, Result, and the PerSecond/PerMinute/PerHour constructors), and lua.go, which embeds two Lua scripts (allowN and allowAtMost) implementing the GCRA algorithm atomically inside Redis. Limiter wraps a minimal rediser interface (Eval, EvalSha, ScriptExists, ScriptLoad, Del, plus read-only variants) that any go-redis v9 client already satisfies, so there is no dependency-injection framework, just a narrow interface boundary against go-redis. Data flows from a caller’s Allow/AllowN/AllowAtMost call, through ARGV values (burst, rate, period, cost) passed into the Lua script, to a single atomic Redis key (prefixed rate:), whose reply is parsed back into a Result. The two Lua scripts duplicate their time-computation boilerplate rather than sharing a template, which is the main coupling risk if the underlying algorithm ever needs to change.

Tech Stack A Go 1.19 module with one runtime dependency, github.com/redis/go-redis/v9 (v9.0.2), used for the Redis client and Lua script execution primitives; stretchr/testify v1.8.1 is a dev-only test dependency. Indirect dependencies are go-redis’s own transitive packages (xxhash, go-rendezvous for consistent hashing, yaml.v3 pulled in by testify). There is no web framework, ORM, or bundler involved — build tooling is a plain Makefile plus Travis CI (.travis.yml) and a renovate.json for automated dependency-update PRs. It ships as an importable library rather than a standalone service.

Code Quality The only tests are rate_test.go and example_test.go, which use testify’s require package against a live Redis instance (redis.NewRing) rather than mocks, so running the suite needs a real Redis server despite the rediser interface existing. Naming follows standard Go conventions (exported Limiter/Limit/Result, unexported internals), and errors are propagated as (T, error) throughout with none observed being swallowed. Numeric values returned from the Lua script are parsed with strconv and blind type assertions (e.g. values[0].(int64)), which would panic rather than return an error if Redis ever returned an unexpected shape — a fragility point worth noting. CI runs on Travis, and formatting for non-Go files is enforced via a .prettierrc.

API Design The public surface is intentionally tiny: NewLimiter, Allow/AllowN/AllowAtMost, Reset, and three Limit constructors, so getting started requires little more than constructing a go-redis client. Result exposes exactly the fields an HTTP handler needs (Allowed, Remaining, RetryAfter, ResetAfter) to build a 429 response and Retry-After header without touching Lua or Redis details directly. Distinguishing AllowN (reject if capacity is insufficient) from AllowAtMost (grant a reduced amount) as separate named methods is a nice ergonomic touch few comparable Go rate-limiter packages surface explicitly. Documentation is limited to a single README example with no extended godoc, but the API’s small surface makes that example cover the common path well.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search