Token-bucket rate limiting for Go io.Reader / io.Writer, with per-key isolation and thread-safe controllers.
package main
import (
"io"
"log"
"strings"
"github.com/lzle/ratelimit"
)
func main() {
limiter, err := ratelimit.NewRateLimiter(map[string]ratelimit.RateLimitConfig{
"user-a": {BandwidthQuota: 1024}, // bytes per second
})
if err != nil {
log.Fatal(err)
}
key := "user-a"
r := limiter.GetReader(key, strings.NewReader("hello ratelimit"))
w := limiter.GetWriter(key, io.Discard)
if _, err := io.Copy(w, r); err != nil {
log.Fatal(err)
}
if err := limiter.Close(key); err != nil {
log.Fatal(err)
}
}- Quota is bytes per second (
BandwidthQuota). - Each
GetReader/GetWriteracquires the key — balance withClose(key)or references accumulate. - Internals: token bucket, 50ms refill window, min burst 64 bytes per window.
go test ./... -count=1The flowctrl package is largely based on CubeFS util/flowctrl. See flowctrl/NOTICE for attribution and upstream licensing.
This repository is MIT licensed for the parts authored here (Copyright (c) 2026 lzle). Third-party code in flowctrl/ remains subject to the Apache License 2.0 of the CubeFS project; see flowctrl/NOTICE.