go-limiter

A dependency-free Go rate limiting library with a pluggable Store interface, an in-memory backend, and HTTP middleware.

Library
Go
vv1.2.0
722stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity36
Maintenance28
Community40
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
80/100Excellent
Architecture85
Code Quality85
Innovation70
Learning Curve80

go-limiter is a rate limiting library for Go built entirely on the standard library, with zero third-party dependencies. It defines a small Store interface (Take, Get, Set, Burst, Close) that any storage backend can implement, and ships with an in-memory implementation, memorystore, that serves already-seen keys from a lock-free sync.Map read path and only takes a per-bucket mutex when a token count actually changes.

Beyond the core interface and memory store, go-limiter includes noopstore for testing and development environments where rate limiting should be bypassed entirely, and an httplimit package that wraps any http.Handler with rate limiting middleware, automatically setting the IETF-recommended X-RateLimit-* and Retry-After headers. A companion package, go-redisstore, from the same author implements the same Store interface against Redis for distributed, multi-instance rate limiting.

What You Get

  • A minimal Store interface (Take/Get/Set/Burst/Close) that any storage backend can implement
  • memorystore, a high-throughput in-memory store backed by sync.Map and per-key token buckets
  • httplimit middleware that wraps http.Handler and sets IETF-recommended rate-limit headers automatically
  • noopstore, a pass-through store useful for tests and local development where limits should not apply
  • An in-repo benchmark suite comparing throughput and allocations against other popular Go rate limiters

Common Use Cases

  • Rate limiting public HTTP APIs by client IP address or API key
  • Bypassing rate limiting in test and local development environments via noopstore
  • Implementing a custom distributed store (e.g. Redis-backed) against the shared Store interface
  • Temporarily bursting extra tokens onto a specific key’s bucket during expected traffic spikes

Under The Hood

Architecture The core limiter package is a single-file interface definition (store.go) that every backend implements; memorystore and noopstore both depend on it, not the reverse, and assert compliance at compile time via var _ limiter.Store = (*store)(nil). memorystore layers a background purge goroutine over a sync.Map of per-key buckets, and pulls a private low-level clock helper from internal/fasttime. httplimit sits one layer above, adapting any limiter.Store into standard http.Handler middleware via a configurable KeyFunc. This is a small, cleanly layered library — core interface, swappable stores, HTTP adapter — with no circular dependencies, though changing the Store interface itself would ripple through every consumer, including the external go-redisstore package.

Tech Stack Go 1.25, standard library only — go.mod declares no external dependencies for the core packages (net/http, sync, sync/atomic, context, time, math). A Makefile drives build, test, and benchmark tasks, and GitHub Actions runs make test-acc across macOS, Ubuntu, and Windows plus a cross-compilation matrix spanning seven target platforms. The benchmarks/ directory imports several third-party rate limiting libraries, but only within test files for comparison — none leak into the public API.

Code Quality Twelve test files span memorystore (unit, example, and benchmark tests), noopstore, httplimit, and a dedicated comparison suite against five other Go rate limiters. Every exported method returns an explicit error per Go convention, with a documented sentinel ErrStopped for the stopped-store case. Naming is idiomatic Go throughout, with doc comments on every exported symbol. CI exercises the full test suite across three operating systems and validates builds across seven GOOS targets — thorough coverage for a library this size, though no linter configuration is checked in.

What Makes It Unique The standout design choice is the lock-free read path: existing keys are served from a sync.Map without any lock, and expiry is handled by a single periodic sweep goroutine rather than a per-key timer — a decision the code’s own comments say was arrived at after benchmarking showed per-item expiration goroutines caused more contention, not less. That performance-oriented design is validated in-repo against comparable libraries via make benchmarks. The rate limiting model itself (token bucket) is standard; the innovation is in the low-level concurrency engineering rather than a new algorithm.

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