Skip to main content
Version: Next

Limiter

The Limiter middleware for Fiber throttles repeated requests to public APIs or endpoints such as password resets. It's also useful for API clients, web crawlers, or other tasks that need rate limiting.

note

This middleware uses our Storage package to support various databases through a single interface. The default configuration for this middleware saves data to memory, see the examples below for other databases.

note

This module does not share state with other processes/servers by default.

Signatures

func New(config ...Config) fiber.Handler

Examples

Import the middleware package:

import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/limiter"
)

Once your Fiber app is initialized, use the middleware like this:

// Initialize default config
app.Use(limiter.New())

// Or extend your config for customization
app.Use(limiter.New(limiter.Config{
Next: func(c fiber.Ctx) bool {
return c.IP() == "127.0.0.1"
},
Max: 20,
MaxFunc: func(c fiber.Ctx) int {
return 20
},
Expiration: 30 * time.Second,
KeyGenerator: func(c fiber.Ctx) string {
return c.Get("x-forwarded-for")
},
LimitReached: func(c fiber.Ctx) error {
return c.SendFile("./toofast.html")
},
Storage: myCustomStorage{},
}))

Sliding window

Instead of using the standard fixed window algorithm, you can enable the sliding window algorithm.

An example configuration is:

app.Use(limiter.New(limiter.Config{
Max: 20,
Expiration: 30 * time.Second,
LimiterMiddleware: limiter.SlidingWindow{},
}))

Each new window also considers the previous one (if any). The rate is calculated as:

weightOfPreviousWindow = previousWindowRequests * (elapsedInCurrentWindow / Expiration)
rate = weightOfPreviousWindow + currentWindowRequests

Dynamic limit

You can also calculate the limit dynamically using the MaxFunc parameter. It receives the request context and allows you to compute a different limit for each request.

Example:

app.Use(limiter.New(limiter.Config{
MaxFunc: func(c fiber.Ctx) int {
return getUserLimit(ctx.Param("id"))
},
Expiration: 30 * time.Second,
}))

Config

PropertyTypeDescriptionDefault
Nextfunc(fiber.Ctx) boolNext defines a function to skip this middleware when it returns true.nil
MaxintMaximum number of recent connections within Expiration seconds before sending a 429 response.5
MaxFuncfunc(fiber.Ctx) intFunction that calculates the maximum number of recent connections within Expiration seconds before sending a 429 response.A function that returns cfg.Max
KeyGeneratorfunc(fiber.Ctx) stringFunction to generate custom keys; uses c.IP() by default.A function using c.IP() as the default
Expirationtime.DurationDuration to keep request records in memory.1 * time.Minute
LimitReachedfiber.HandlerCalled when a request exceeds the limit.A function sending a 429 response
SkipFailedRequestsboolWhen set to true, requests with status code ≥ 400 aren't counted.false
SkipSuccessfulRequestsboolWhen set to true, requests with status code < 400 aren't counted.false
DisableHeadersboolWhen set to true, the middleware omits rate limit headers (X-RateLimit-* and Retry-After).false
Storagefiber.StoragePersists middleware state.An in-memory store for this process only
LimiterMiddlewareLimiterHandlerSelects the algorithm implementation.A new Fixed Window Rate Limiter
note

A custom store can be used if it implements the Storage interface - more details and an example can be found in store.go.

Default Config

var ConfigDefault = Config{
Max: 5,
MaxFunc: func(c fiber.Ctx) int {
return 5
},
Expiration: 1 * time.Minute,
KeyGenerator: func(c fiber.Ctx) string {
return c.IP()
},
LimitReached: func(c fiber.Ctx) error {
return c.SendStatus(fiber.StatusTooManyRequests)
},
SkipFailedRequests: false,
SkipSuccessfulRequests: false,
DisableHeaders: false,
LimiterMiddleware: FixedWindow{},
}

Custom Storage/Database

You can use any storage from our storage package.

storage := sqlite3.New() // From github.com/gofiber/storage/sqlite3

app.Use(limiter.New(limiter.Config{
Storage: storage,
}))