Configuration: HTTP cache

This page documents the cache directive for configuring Ferron’s in-memory HTTP response cache. The cache stores complete GET response representations, serves HEAD from cached GET metadata, follows standard HTTP caching semantics by default, and understands a subset of LiteSpeed Cache response headers for LSCache-aware applications.

The cache applies to final HTTP responses produced by static file serving, reverse proxying, and other response stages.

cache

{
    cache {
        max_entries 2048
    }
}

example.com {
    cache {
        max_response_size 1048576
        litespeed_override_cache_control false
        vary Accept-Encoding Accept-Language
        ignore Set-Cookie
    }

    location /admin {
        cache false
    }
}

At HTTP host scope, cache can be written either as a block or as a boolean flag. Block form enables caching for that scope and configures nested directives. Boolean form is useful when you want to enable or disable inherited caching without changing any nested settings.

Global cache block

Use the global cache { ... } block to configure shared cache capacity.

Nested directiveArgumentsDescriptionDefault
max_entries<int>This directive specifies the maximum number of response entries stored in the shared in-memory HTTP cache. Setting this directive to 0 keeps the module loaded but prevents new entries from being stored.1024

Configuration example:

{
    cache {
        max_entries 4096
    }
}

HTTP host cache block

Use the HTTP host cache { ... } block to enable caching and tune how responses are stored for that host or matching location.

Nested directiveArgumentsDescriptionDefault
max_response_size<int>This directive specifies the maximum response body size, in bytes, that can be buffered and stored in the cache. Responses larger than this limit are still served, but they are not stored.2097152
litespeed_override_cache_control[<bool>]This directive specifies whether X-LiteSpeed-Cache-Control overrides standard response caching headers such as Cache-Control and Expires when Ferron decides whether to store a response and what TTL to use. This mode is intentionally non-standard and is intended only for applications that expect LiteSpeed-style cache semantics.false
vary<string> [<string> ...]This directive specifies additional request headers that are added to the cache key, alongside any standard Vary response headers returned by the origin. This directive can be specified multiple times.none
ignore<string> [<string> ...]This directive specifies response headers that are removed from the stored cache representation while leaving the live response unchanged. This directive can be specified multiple times.none

Configuration example:

example.com {
    cache {
        max_response_size 2097152
        litespeed_override_cache_control
        vary Accept-Encoding Accept-Language
        ignore Set-Cookie
    }
}

Boolean cache form

FormDescriptionDefault
cacheEnables caching for the current HTTP host or location scope.false
cache trueExplicitly enables caching for the current scope.false
cache falseDisables caching for the current scope, which is useful for overriding an inherited cache { ... } block.false

Behavior

Cache eligibility

  • Only GET and HEAD requests perform cache lookups.
  • HEAD requests reuse cached GET representations and return only headers.
  • Non-GET responses are not stored, but they may still trigger LSCache-compatible purge headers.
  • Responses with Vary: * are never stored.
  • Built-in error responses generated after the main HTTP pipeline are not currently stored.

Public and private cache behavior

  • Public responses containing Set-Cookie are not stored.
  • Private responses are partitioned by client context. Ferron currently uses the client IP address, the authenticated username when available, and detected private cookies.
  • If Ferron cannot determine a narrower private cookie set, it falls back to all request cookies for the private cache key.

LSCache-compatible response headers

When the cache module is enabled, Ferron understands the following response headers from upstream applications and origin handlers:

HeaderDescriptionNotes
X-LiteSpeed-Cache-ControlControls cache scope and TTL using LSCache-style directives such as public, private, max-age, s-maxage, no-cache, and no-store.By default, standard HTTP caching rules still take precedence. Enable litespeed_override_cache_control to prefer this header instead.
X-LiteSpeed-VaryAdds LSCache-style vary dimensions.cookie=<name> is supported. value=<name> is not supported yet and causes Ferron to skip cache storage for that response.
X-LiteSpeed-TagAssigns tags to cached responses so they can be purged later.On private responses, public: prefixes remain public tags.
X-LiteSpeed-PurgePurges cached responses by tag, URL, or wildcard.The stale marker currently falls back to an immediate hard purge.
LSC-CookieAdds cache-safe cookie replay metadata.Ferron converts this header to Set-Cookie before sending the response.
X-LiteSpeed-CacheExposes cache hit, miss, or bypass status on outgoing responses.Ferron sets this header itself. Origin-provided values are ignored.

Observability

Metrics

The cache module emits the following metrics:

  • ferron.cache.requests (Counter) — cache hits, misses, and bypasses.
    • Attributes: ferron.cache.result, ferron.cache.scope
  • ferron.cache.entries (Gauge) — current number of cached entries.
  • ferron.cache.stores (Counter) — responses stored in the cache.
    • Attributes: ferron.cache.scope
  • ferron.cache.evictions (Counter) — entries evicted from the cache.
    • Attributes: ferron.cache.reason ("expired" or "size")
  • ferron.cache.purges (Counter) — entries purged through LSCache-compatible controls.
    • Attributes: ferron.cache.scope

Logs

  • DEBUG — logged when Ferron skips cache storage because X-LiteSpeed-Vary: value=... is not supported yet.
  • DEBUG — logged when Ferron skips cache storage because the response body exceeds cache.max_response_size.
  • DEBUG — logged when Ferron performs a purge through X-LiteSpeed-Purge.
  • DEBUG — logged when Ferron receives an LSCache stale purge marker and falls back to a hard purge.

Notes and troubleshooting

  • By default, Ferron treats LSCache response headers as additional cache controls, not as a way to weaken standard HTTP caching rules. Cache-Control, Authorization, Vary, and Set-Cookie constraints still apply.
  • litespeed_override_cache_control changes only response-side store policy and TTL selection. Request-side directives such as Cache-Control: no-cache and Pragma: no-cache still affect cache lookup behavior normally.
  • litespeed_override_cache_control is intentionally non-compliant with RFC 9111 behavior when X-LiteSpeed-Cache-Control is present. Enable it only when the upstream application is written for LiteSpeed-style server cache semantics.
  • X-LiteSpeed-Vary: value=... is not supported yet because Ferron does not currently have a request-time equivalent of LiteSpeed’s rewrite-rule vary environment values.
  • ignore affects only the stored representation. The live response sent to the client still includes those headers unless another module removes them.
  • Global cache { ... } blocks are only for shared cache sizing. They do not enable caching for HTTP hosts by themselves.
  • For static file cache headers such as file_cache_control and etag, see Static file serving.
  • For response header mutation and CORS handling, see HTTP headers and CORS.
  • For reverse proxy configuration, see Reverse proxying.