Skip to main content
Cache middleware for Fiber that intercepts responses and stores the body, Content-Type, and status code under a key derived from the request path and method. Special thanks to @codemicro for contributing this middleware to Fiber core. By default, cached responses expire after five minutes and the middleware stores up to 1 MB of response bodies.

Request Directives

  • Cache-Control: no-cache returns the latest response while still caching it, so the status is always miss
  • Cache-Control: no-store skips caching and always forwards a fresh response
If the response includes a Cache-Control: max-age directive, its value sets the cache entry’s expiration.

Cacheable Status Codes

The middleware caches these RFC 7231 status codes:
  • 200: OK
  • 203: Non-Authoritative Information
  • 204: No Content
  • 206: Partial Content
  • 300: Multiple Choices
  • 301: Moved Permanently
  • 404: Not Found
  • 405: Method Not Allowed
  • 410: Gone
  • 414: URI Too Long
  • 501: Not Implemented
Responses with other status codes result in an unreachable cache status.

Signatures

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

Usage

import (
    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/cache"
    "github.com/gofiber/utils/v2"
)

Basic Example

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

// Or extend the config for customization
app.Use(cache.New(cache.Config{
    Next: func(c fiber.Ctx) bool {
        return fiber.Query[bool](c, "noCache")
    },
    Expiration: 30 * time.Minute,
    DisableCacheControl: true,
}))

Custom Key and Expiration

Customize the cache key and expiration; the HTTP method is appended automatically:
app.Use(cache.New(cache.Config{
    ExpirationGenerator: func(c fiber.Ctx, cfg *cache.Config) time.Duration {
        newCacheTime, _ := strconv.Atoi(c.GetRespHeader("Cache-Time", "600"))
        return time.Second * time.Duration(newCacheTime)
    },
    KeyGenerator: func(c fiber.Ctx) string {
        return utils.CopyString(c.Path())
    },
}))

app.Get("/", func(c fiber.Ctx) error {
    c.Response().Header.Add("Cache-Time", "6000")
    return c.SendString("hi")
})

Cache Invalidation

Use CacheInvalidator to invalidate entries programmatically:
app.Use(cache.New(cache.Config{
    CacheInvalidator: func(c fiber.Ctx) bool {
        return fiber.Query[bool](c, "invalidateCache")
    },
}))

Configuration

Next
func(fiber.Ctx) bool
default:"nil"
Executed before creating the cache entry. Can be used to execute the request without cache creation. If an entry already exists, it will be used. To completely bypass the cache functionality in certain cases, use the skip middleware.
Expiration
time.Duration
default:"5 * time.Minute"
Time that a cached response will live.
CacheHeader
string
default:"X-Cache"
Header on the response that indicates the cache status, with possible return values “hit,” “miss,” or “unreachable.”
DisableCacheControl
bool
default:"false"
Omits the Cache-Control header when set to true.
CacheInvalidator
func(fiber.Ctx) bool
default:"nil"
Executed before checking the cache entry. Can be used to invalidate the existing cache manually by returning true.
DisableValueRedaction
bool
default:"false"
Turns off cache key redaction in logs and error messages when set to true.
KeyGenerator
func(fiber.Ctx) string
Allows you to generate custom keys. The HTTP method is appended automatically.
ExpirationGenerator
func(fiber.Ctx, *cache.Config) time.Duration
default:"nil"
Allows you to generate custom expiration keys based on the request.
Storage
fiber.Storage
default:"In-memory store"
Used to store the state of the middleware.
StoreResponseHeaders
bool
default:"false"
Allows you to store additional headers generated by next middlewares & handler.
MaxBytes
uint
default:"1 * 1024 * 1024"
Maximum number of bytes of response bodies simultaneously stored in cache (~1 MB).
Methods
[]string
default:"[]string{fiber.MethodGet, fiber.MethodHead}"
Specifies the HTTP methods to cache.

Default Config

var ConfigDefault = Config{
    Next:         nil,
    Expiration:   5 * time.Minute,
    CacheHeader:  "X-Cache",
    DisableCacheControl: false,
    CacheInvalidator: nil,
    DisableValueRedaction: false,
    KeyGenerator: func(c fiber.Ctx) string {
        return utils.CopyString(c.Path())
    },
    ExpirationGenerator:  nil,
    StoreResponseHeaders: false,
    Storage:              nil,
    MaxBytes:             1 * 1024 * 1024,
    Methods: []string{fiber.MethodGet, fiber.MethodHead},
}

Common Use Cases

API Response Caching

api := app.Group("/api")
api.Use(cache.New(cache.Config{
    Expiration: 10 * time.Minute,
    KeyGenerator: func(c fiber.Ctx) string {
        return c.Path() + "?" + c.Request().URI().QueryArgs().String()
    },
}))

Per-Route Cache Duration

app.Get("/static", cache.New(cache.Config{
    Expiration: 1 * time.Hour,
}), staticHandler)

app.Get("/dynamic", cache.New(cache.Config{
    Expiration: 30 * time.Second,
}), dynamicHandler)

Conditional Caching

app.Use(cache.New(cache.Config{
    Next: func(c fiber.Ctx) bool {
        // Don't cache authenticated requests
        return c.Get("Authorization") != ""
    },
}))

Build docs developers (and LLMs) love