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 directive | Arguments | Description | Default |
|---|---|---|---|
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 directive | Arguments | Description | Default |
|---|---|---|---|
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
| Form | Description | Default |
|---|---|---|
cache | Enables caching for the current HTTP host or location scope. | false |
cache true | Explicitly enables caching for the current scope. | false |
cache false | Disables caching for the current scope, which is useful for overriding an inherited cache { ... } block. | false |
Behavior
Cache eligibility
- Only
GETandHEADrequests perform cache lookups. HEADrequests reuse cachedGETrepresentations and return only headers.- Non-
GETresponses 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-Cookieare 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:
| Header | Description | Notes |
|---|---|---|
X-LiteSpeed-Cache-Control | Controls 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-Vary | Adds 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-Tag | Assigns tags to cached responses so they can be purged later. | On private responses, public: prefixes remain public tags. |
X-LiteSpeed-Purge | Purges cached responses by tag, URL, or wildcard. | The stale marker currently falls back to an immediate hard purge. |
LSC-Cookie | Adds cache-safe cookie replay metadata. | Ferron converts this header to Set-Cookie before sending the response. |
X-LiteSpeed-Cache | Exposes 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
- Attributes:
ferron.cache.entries(Gauge) — current number of cached entries.ferron.cache.stores(Counter) — responses stored in the cache.- Attributes:
ferron.cache.scope
- Attributes:
ferron.cache.evictions(Counter) — entries evicted from the cache.- Attributes:
ferron.cache.reason("expired"or"size")
- Attributes:
ferron.cache.purges(Counter) — entries purged through LSCache-compatible controls.- Attributes:
ferron.cache.scope
- Attributes:
Logs
DEBUG— logged when Ferron skips cache storage becauseX-LiteSpeed-Vary: value=...is not supported yet.DEBUG— logged when Ferron skips cache storage because the response body exceedscache.max_response_size.DEBUG— logged when Ferron performs a purge throughX-LiteSpeed-Purge.DEBUG— logged when Ferron receives an LSCachestalepurge 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, andSet-Cookieconstraints still apply. litespeed_override_cache_controlchanges only response-side store policy and TTL selection. Request-side directives such asCache-Control: no-cacheandPragma: no-cachestill affect cache lookup behavior normally.litespeed_override_cache_controlis intentionally non-compliant with RFC 9111 behavior whenX-LiteSpeed-Cache-Controlis 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.ignoreaffects 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_controlandetag, see Static file serving. - For response header mutation and CORS handling, see HTTP headers and CORS.
- For reverse proxy configuration, see Reverse proxying.