This package provides extensible rate limiter module in Go. There are 2 main extensible points:
- Rate limit algorithm (fixed window, sliding window, leaky bucket, etc.)
- Data store - to track request count by key (in-memory, Redis, Hazelcast, etc.)
This is the simplest algorithm for rate limiting. It divides the time into fixed window. For example a rate of 5 per 12 minutes gives us the following time windows:
- hh:00 - hh:11
- hh:12 - hh:23
- hh:24 - hh:35
- hh:36 - hh:47
- hh:48 - hh:59
Where hh is any hours in the clock. This algorithm is susceptible to spike near the window boundaries. For instance 5 requests at hh:11 and 5 requests at hh:12 are allowed because they happen to fall on 2 windows although if you see it without the windows, you are allowing 10 requests within 2 minutes.
This is the simplest storage i.e. relying on in-mem data structure that is map to keep track of the request count. This is susceptible to data loss when the app restarts because the data is not persisted on disk.
go get github.com/yonasstephen/ratelimiter
Use it in your code
import github.com/yonasstephen/ratelimiter
func main() {
repo := mocks.NewInMemRepository()
clock := clock.Clock()
// setting the limit to 5 per minute
r := ratelimiter.NewFixedWindowRateLimiter("5", time.Minute, repo, clock)
// increasing the rate limit count for user_123
res, err := r.Allow(context.Background(), "user_123")
if err != nil {
fmt.Fatal("failed to check rate limit")
}
fmt.Println(res)
}
There exists an example on how to use the ratelimiter module as a HTTP middleware as well in the examples/httpserver folder.
These are future improvements that can be made on this module:
- Thread-safe implementation of in-mem repository
- Integration test for examples/httpserver
- Sliding window algorithm implementation
- Redis repository implementation
Run tests
make test
If you make any changes to interface contract, you can run go generate to regenerate the mocks
make generate