FluxRate is a high-performance, production-ready, distributed rate limiting library for Go and Redis. It is built for resilience, providing automatic, thread-safe in-memory fallback if your Redis cluster goes down, and recovers seamlessly when Redis is back online.
It implements 5 advanced rate limiting algorithms using optimized Lua scripts, and provides drop-in middlewares for popular Go web frameworks (Gin, Echo, net/http).
- 🛠️ 5 Rate Limiting Algorithms:
- GCRA (Generic Cell Rate Algorithm): The industry standard for cell/leaky-bucket traffic shaping.
- Token Bucket: Perfect for supporting bursty traffic patterns with constant refill rates.
- Sliding Window Log: 100% precise sliding window rate limiting.
- Sliding Window Counter: Extremely memory-efficient sliding window approximation.
- Fixed Window: Simple, high-speed, atomic block-based limiter.
- 🛡️ Resilient Local Fallback: Automatically degrades to a high-performance, thread-safe local in-memory limiter if Redis becomes unreachable. Failing-open or failing-closed options are supported.
- 🔗 Universal Redis Compatibility: Supports single-node Redis, Redis Sentinel, and Redis Cluster.
- 🚀 Pre-Built Middlewares: Integrated support for Gin, Echo, and standard
net/httphandlers. - 📊 Interactive CLI Traffic Simulator: An educational tool to visualize and compare rate limiters under live workloads (constant, spiky, sine wave traffic).
graph TD
Client[Client Request] --> MW[FluxRate Middleware]
MW --> KeyGen[Generate Client Key]
KeyGen --> RedisCheck{Is Redis Reachable?}
%% Redis Path
RedisCheck -- Yes --> RedisLimiter[Run Optimized Lua Script]
RedisLimiter --> RedisResult{Allowed?}
%% Fallback Path
RedisCheck -- No / Timeout --> LogWarn[Log Warning]
LogWarn --> FallbackLimiter[Swap to Local In-Memory Limiter]
FallbackLimiter --> FallbackResult{Allowed?}
%% Decision handling
RedisResult -- Yes --> ServeHTTP[Forward to Handler]
RedisResult -- No --> BlockHTTP[Return HTTP 429 Too Many Requests]
FallbackResult -- Yes --> ServeHTTP
FallbackResult -- No --> BlockHTTP
ServeHTTP --> InjectHeaders[Inject HTTP Headers: X-RateLimit-*]
BlockHTTP --> InjectRetryHeaders[Inject Retry-After Header]
go get github.com/ayd1ndemirci/fluxratepackage main
import (
"context"
"fmt"
"time"
"github.com/ayd1ndemirci/fluxrate"
)
func main() {
// Connect to Redis
rdb := fluxrate.NewRedis("localhost:6379")
// Create a GCRA rate limiter: allows 10 requests per 10 seconds
limiter := fluxrate.NewGCRA(
rdb.Client,
10, // limit
10*time.Second, // window size
fluxrate.WithKeyPrefix("api:rate:"), // optional prefix
)
ctx := context.Background()
key := "user_ip_127.0.0.1"
res, err := limiter.Allow(ctx, key)
if err != nil {
fmt.Printf("Rate limit evaluation failed: %v\n", err)
return
}
if res.Allowed {
fmt.Printf("Request allowed. Remaining quota: %d. Reset after: %v\n", res.Remaining, res.ResetAfter)
} else {
fmt.Printf("Rate limit exceeded! Retry after: %v\n", res.RetryAfter)
}
}package main
import (
"github.com/ayd1ndemirci/fluxrate"
fluxgin "github.com/ayd1ndemirci/fluxrate/middleware/gin"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
rdb := fluxrate.NewRedis("localhost:6379")
// Token Bucket: Capacity of 20, refills 5 tokens per second
limiter := fluxrate.NewTokenBucket(rdb.Client, 20, 5.0)
// Rate limit based on client IP address
keyFunc := func(c *gin.Context) string {
return "ip:" + c.ClientIP()
}
r.Use(fluxgin.Handler(limiter, keyFunc))
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
r.Run(":8080")
}When using pre-built middlewares, responses automatically include RFC-compliant headers:
| Header | Description |
|---|---|
X-RateLimit-Limit |
The maximum number of requests allowed in the window. |
X-RateLimit-Remaining |
The number of remaining requests allowed within the current window. |
X-RateLimit-Reset |
The number of seconds remaining until the rate limit resets/refills. |
Retry-After |
(Sent on HTTP 429 only) The number of seconds the client must wait before retrying. |
FluxRate includes a live traffic simulator to let you test and analyze how different algorithms shape traffic. It starts a mock local API server and simulates request loads (sine waves, spiky bursts, or constant loads) against it.
# Run simulator with GCRA and sinusoidal traffic
go run cmd/simulator/main.go --algo=gcra --traffic=sine --duration=20s
# Run simulator in memory-only mode (no Redis required)
go run cmd/simulator/main.go --algo=token_bucket --traffic=bursty
# Run simulator with a real Redis database
go run cmd/simulator/main.go --algo=sliding_window_counter --redis=localhost:6379When running, the simulator renders a real-time ASCII dashboard showing allowed vs. blocked requests and latencies:
=============================================================
FLUXRATE SIMULATOR DASHBOARD (GCRA)
=============================================================
Target Limit : 10 requests per 2s
Traffic Pattern: SINE
Elapsed Time : 8s / 20s
-------------------------------------------------------------
Total Requests : 124 Success Rate: 56.45%
Allowed (.) : 70 Blocked (X) : 54
Errors (E) : 0
Latency : Min: 45µs | Avg: 1.25ms | Max: 15.34ms
-------------------------------------------------------------
Traffic Flow Timeline (last 60 requests):
[....XXXX....XXXX....X.X.X.X.X.X.X.X.X.X.X..XXXX....XXXX....]
(. = Allowed, X = Blocked, E = Error)
=============================================================
| Algorithm | Redis Command Complexity | Memory Footprint (Redis) | Burst Capacity | Accuracy | Best Use Case |
|---|---|---|---|---|---|
| GCRA | O(1) |
Very Low (1 Key) | High (Configurable) | High | API Rate Limiting, Traffic Pacing |
| Token Bucket | O(1) |
Low (1 Hash) | High | High | Burst Handling API Gateways |
| Sliding Window Log | O(log N) |
High (Grows with reqs) | Low | 100% | High-value, low-frequency security operations |
| Sliding Window Counter | O(1) |
Low (2 Keys) | Medium | Approximate | Large scale web apps with strict memory targets |
| Fixed Window | O(1) |
Very Low (1 Key) | None | Low | Basic limiting where window resets are acceptable |
This project is licensed under the MIT License - see the LICENSE file for details.