Rate Limiting
Rate limiting protects your application from abuse by restricting how many requests a client can make within a time window. Nimbus provides middleware.RateLimit() as an in-memory rate limiter you can apply globally or to specific route groups.
Basic usage
The RateLimit middleware takes three parameters: the request limit, the time window, and a key function that identifies each client:
app.Router.Use(middleware.RateLimit(100, time.Minute, func(r *http.Request) string {
return r.RemoteAddr
}))
This allows 100 requests per minute per IP address. When the limit is exceeded, the middleware returns a 429 Too Many Requests JSON response.
Parameters
limit int— Maximum number of requests allowed in the window.window time.Duration— The time period for the limit (e.g.time.Minute,time.Hour).keyFn func(*http.Request) string— Extracts a unique key per client. If it returns an empty string,RemoteAddris used as fallback.
Per-IP limiting
The most common approach is to rate limit by client IP address:
app.Router.Use(middleware.RateLimit(60, time.Minute, func(r *http.Request) string {
return r.RemoteAddr
}))
Custom key functions
You can rate limit by any identifier — for example, by API key or authenticated user ID:
// Rate limit by API key
app.Router.Use(middleware.RateLimit(1000, time.Hour, func(r *http.Request) string {
return r.Header.Get("X-API-Key")
}))
// Rate limit by authenticated user
app.Router.Use(middleware.RateLimit(200, time.Minute, func(r *http.Request) string {
user := auth.UserFromContext(r.Context())
if user != nil {
return user.GetID()
}
return r.RemoteAddr
}))
Rate limiting specific routes
Apply stricter limits to sensitive endpoints like login or password reset:
authGroup := app.Router.Group("/auth")
authGroup.Use(middleware.RateLimit(5, time.Minute, func(r *http.Request) string {
return r.RemoteAddr
}))
authGroup.Post("/login", HandleLogin)
authGroup.Post("/reset-password", HandlePasswordReset)
Response on limit exceeded
When a client exceeds the limit, Nimbus returns a JSON response with HTTP status 429:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{"error": "rate limit exceeded"}
How it works internally
The rate limiter stores a counter and window start time per key in memory. When a request arrives:
- If the key is new or the window has expired, the counter resets to 1.
- If the counter is below the limit, it increments and the request proceeds.
- If the counter has reached the limit, the request is rejected with 429.
This is an in-memory implementation suitable for single-server deployments. For distributed systems, consider implementing a custom middleware backed by Redis or a similar shared store.