Rate Limiting
Protect routes from excessive traffic using IP and route-based request throttling middleware.
The router package includes rate limiting middleware for throttling repeated requests from the same client.
Rate limiting is useful for:
- protecting public endpoints
- reducing abuse and accidental traffic spikes
- limiting expensive handlers
- slowing down brute-force attempts
- adding lightweight per-route traffic control
The limiter tracks requests by client and route, then rejects requests that arrive too frequently.
When a client exceeds the configured limit, the router responds with:
429 Too Many RequestsBasic Usage
r.Use(router.RateLimit(50 * time.Millisecond))This allows one request per client and route every 50ms.
That is approximately:
20 requests per secondExample
package main
import (
"log/slog"
"net/http"
"os"
"time"
"github.com/netlifeguru/router"
)
func main() {
r := router.New()
r.Use(router.RateLimit(50 * time.Millisecond))
r.HandleFunc("/", "GET", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
w.Write([]byte("Success! You are not rate-limited."))
})
if err := r.ListenAndServe(":8000"); err != nil {
slog.Error("failed to start server", "error", err)
os.Exit(1)
}
}Run the application:
go run .Test the endpoint:
curl http://localhost:8000/If requests are sent too quickly, the router returns:
429 Too Many RequestsCustom Configuration
The rate limiter can be customized using configuration options.
func CustomRateLimitOpt(cfg *router.RateLimitConfig) {
cfg.TTL = 5 * time.Minute
cfg.CleanupInterval = 1 * time.Minute
}Then pass the option to the middleware:
r.Use(router.RateLimit(50*time.Millisecond, CustomRateLimitOpt))Full example:
package main
import (
"log/slog"
"net/http"
"os"
"time"
"github.com/netlifeguru/router"
)
func CustomRateLimitOpt(cfg *router.RateLimitConfig) {
cfg.TTL = 5 * time.Minute
cfg.CleanupInterval = 1 * time.Minute
}
func main() {
r := router.New()
r.Use(router.RateLimit(50*time.Millisecond, CustomRateLimitOpt))
r.HandleFunc("/", "GET", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
w.Write([]byte("Success! You are not rate-limited."))
})
if err := r.ListenAndServe(":8000"); err != nil {
slog.Error("failed to start server", "error", err)
os.Exit(1)
}
}Configuration Options
TTL
TTL defines how long a client tracking record is kept in memory.
cfg.TTL = 5 * time.MinuteLonger TTL values remember clients for a longer period of time.
CleanupInterval
CleanupInterval defines how often old client tracking records are removed.
cfg.CleanupInterval = 1 * time.MinuteShorter cleanup intervals remove expired records more frequently, while longer intervals reduce cleanup overhead.
Notes
Rate limiting is registered as middleware.
When applied globally:
r.Use(router.RateLimit(50 * time.Millisecond))it affects all routes.
When applied to a route group, it only affects routes inside that group.
The limiter is intended as a lightweight application-level guard. For large distributed systems, combine it with infrastructure-level rate limiting such as reverse proxies, API gateways, or load balancers.