NVIDIA/go-ratelimit
Go
Captured source
source ↗NVIDIA/go-ratelimit
Description: High-performance distributed rate limiting library for Go with Redis backend, sliding window algorithm, and dynamic configuration support
Language: Go
License: Apache-2.0
Stars: 30
Forks: 4
Open issues: 1
Created: 2025-10-14T04:41:09Z
Pushed: 2025-11-13T05:29:01Z
Default branch: main
Fork: no
Archived: no
README:
go-ratelimit - Redis-based Rate Limiting for Go
NVIDIA® go-ratelimit is a comprehensive, Redis-based rate limiting library for Go HTTP services. It provides high-performance, distributed rate limiting with support for both request count and bandwidth (bytes served) limits, making it ideal for protecting APIs and managing resource consumption in cloud-native applications.
For the latest stable version ensure you are on the main branch.
Features
- Dual Rate Limiting: Limits both request count and response size (bytes served)
- Sliding Window Algorithm: More accurate than fixed windows, prevents traffic spikes at window boundaries
- Redis-Based: Works across multiple server instances in a distributed environment
- Resilient Fallback: Maintains rate limits in memory if Redis becomes unavailable
- Dynamic Per-Client Configuration: Customize rate limits for each client at runtime
- RFC Compliant Headers: Returns standard rate limit headers for client awareness
- Customizable Key Generation: Limit by client ID, IP address, route, or any combination
- Header-Based Rate Limiting: Rate limit by any HTTP header (API key, tenant ID, custom fields, etc.)
- Advanced Header Options: Sanitizers, prefixes, fallbacks, and composite keys from multiple headers
Installation
go get github.com/NVIDIA/go-ratelimit/pkg/ratelimit
Quick Start
import (
"github.com/NVIDIA/go-ratelimit/pkg/ratelimit"
"github.com/redis/go-redis/v9"
)
func main() {
// Create Redis client
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
// Create rate limiter with default options
options := ratelimit.DefaultOptions(rdb)
service := ratelimit.New(options)
// Create your HTTP handler
mux := http.NewServeMux()
mux.HandleFunc("/api/resource", handleResource)
// Apply rate limiting middleware
handler := service.Middleware()(mux)
// Start server
http.ListenAndServe(":8080", handler)
}Configuration Options
// Create with custom options
options := ratelimit.Options{
Redis: redisClient,
Prefix: "myapp",
RequestLimit: 100, // 100 requests per window
ByteLimit: 5 * 1024 * 1024, // 5MB per window
Window: time.Minute, // 1 minute window
KeyFunc: ratelimit.KeyByClientIDAndRoute("client123"),
Logger: myCustomLogger, // Optional: custom logger for rate limit events
}
service := ratelimit.New(options)Logger Interface
You can provide a custom logger that implements the middleware.Logger interface:
type Logger interface {
Info(msg string, keysAndValues ...interface{})
Error(msg string, keysAndValues ...interface{})
}If no logger is provided, the service uses a no-op logger by default.
Key Functions
The library provides several built-in key functions:
// Limit by client ID
ratelimit.KeyByClientID("client123")
// Limit by client ID and route
ratelimit.KeyByClientIDAndRoute("client123")
// Limit by IP address only
ratelimit.KeyByIP
// Limit by HTTP header (NEW)
ratelimit.KeyByHeader("X-API-Key")
ratelimit.KeyByHeader("X-Tenant-ID")
ratelimit.KeyByHeader("X-Custom-Field")
// Advanced header options (NEW)
ratelimit.KeyByHeaderWithOptions(utils.HeaderKeyOptions{
HeaderName: "X-Tenant-ID",
Prefix: "tenant",
Sanitizer: utils.AlphanumericSanitizer,
DefaultValue: "default-tenant",
CaseSensitive: false,
})
// Multiple headers composite key (NEW)
ratelimit.KeyByMultipleHeaders([]string{"X-Tenant-ID", "X-Region"}, ":")
// Header with fallback chain (NEW)
ratelimit.KeyByHeaderWithFallback([]string{"X-API-Key", "Authorization"})
// Custom key function
myKeyFunc := func(r *http.Request) string {
return "custom:" + r.URL.Path
}Built-in Sanitizers
The library provides several sanitizer functions for cleaning header values:
// Removes non-alphanumeric characters utils.AlphanumericSanitizer // Validates and normalizes UUIDs utils.UUIDSanitizer // Truncates strings to a maximum length utils.MaxLengthSanitizer(100)
📖 [Detailed Header-Based Rate Limiting Guide](docs/HEADER_BASED_RATE_LIMITING.md)
Selective Rate Limiting
You can apply rate limiting only to specific endpoints:
// Create a matcher for specific paths
matcher := ratelimit.MatchAny(
ratelimit.MatchPathExact("/api/expensive"),
ratelimit.MatchPathPrefix("/api/users/"),
ratelimit.MatchPathRegex("^/api/.*\\.json$"),
)
// Apply rate limiting only to paths matching the criteria
handler := service.SelectiveMiddleware(matcher)(mux)Available matchers:
MatchPathExact(path)- Matches exact pathMatchPathPrefix(prefix)- Matches paths with a specific prefixMatchPathRegex(pattern)- Matches paths using a regular expressionMatchAny(matchers...)- Matches if any matcher matchesMatchNone(matchers...)- Matches if no matcher matches
Service API
The Service struct provides the following methods:
// Middleware application service.Middleware() // Apply rate limiting to all requests service.SelectiveMiddleware(matcher) // Apply rate limiting to specific paths // Configuration management service.SetClientConfig(clientID, reqLimit, byteLimit, windowSecs) // Set client-specific limits service.ResetClientConfig(clientID) // Reset to defaults service.RegisterConfigAPI(mux) // Register config endpoints // Access internals service.GetLimiter() // Get underlying DynamicLimiter
Dynamic Client Configuration
Programmatic Configuration
// Set custom limits for a specific client
service.SetClientConfig("premium-client",
1000, // 1000 requests
10 * 1024 * 1024, // 10MB
60) // per minute
// Reset client to default configuration
service.ResetClientConfig("client-id")REST API Configuration
Register the configuration API endpoints:
// Register the configuration API service.RegisterConfigAPI(mux)
This adds the following endpoints:
GET /admin/config/{clientID}- Get client's configurationPUT /admin/config/{clientID}- Update client's configurationDELETE /admin/config/{clientID}- Reset client to default configuration
Example API usage:
# Get a client's configuration curl -H...
Excerpt shown — open the source for the full document.