Skip to main content

Cache Configuration

The [cache] section controls PRISM's in-memory cache for rendered HTML. Caching avoids redundant renders and dramatically reduces response times for repeat requests.

TOML Example

[cache]
enabled = true
max_entries = 10000
max_memory_bytes = 268435456
default_ttl_secs = 3600
grace_period_secs = 300
strip_query_params = ["utm_*", "fbclid", "gclid", "msclkid", "_ga"]
error_ttl_secs = 30
skip_authenticated = true
synthesize_cache_control = true

[[cache.rules]]
pattern = "/blog/**"
ttl_secs = 86400

[[cache.rules]]
pattern = "/products/**"
ttl_secs = 7200

[[cache.rules]]
pattern = "/special-page"
ttl_secs = 60

Parameters

ParameterTypeDefaultDescription
enabledBooleantrueEnable or disable caching entirely
max_entriesInteger10000Maximum number of cached pages
max_memory_bytesInteger268435456 (256 MiB)Maximum memory for cached content
default_ttl_secsInteger3600 (1 hour)Default time-to-live for cached entries
grace_period_secsInteger300 (5 minutes)Serve stale content while revalidating in background
rulesArray of {pattern, ttl_secs}[]Path-specific TTL overrides using glob patterns
strip_query_paramsArray of Strings["utm_*", "fbclid", "gclid", "msclkid", "_ga"]Query parameters to strip from cache keys (supports globs)
error_ttl_secsInteger30TTL for caching error responses (status >= 500). 0 = do not cache errors
skip_authenticatedBooleantrueSkip caching for requests with Authorization header or session cookies
synthesize_cache_controlBooleantrueAdd Cache-Control header to rendered responses if origin did not provide one
varyArray of Strings[]Request headers that fragment the cache key AND are forwarded to Chrome during render. See vary below.

Detailed Explanation

max_memory_bytes

The default is 256 MiB (268435456 bytes). When this limit is reached, the least recently used entries are evicted. Size your allocation based on average page size and expected unique URLs.

grace_period_secs

When a cached entry expires, PRISM can still serve the stale version for up to grace_period_secs while triggering a background re-render. This prevents cache stampedes and ensures visitors never wait for a cold render.

rules

TTL rules are evaluated in order; the first matching glob pattern wins. If no rule matches, default_ttl_secs is used.

[[cache.rules]]
pattern = "/blog/**"
ttl_secs = 86400 # Blog posts: 24 hours

[[cache.rules]]
pattern = "/products/**"
ttl_secs = 7200 # Product pages: 2 hours

Place more specific patterns before broader ones, since the first match wins.

strip_query_params

Marketing and analytics query parameters are stripped from cache keys to avoid duplicate cache entries for the same page. Supports glob patterns (e.g., utm_* matches utm_source, utm_medium, utm_campaign, etc.).

skip_authenticated

In render-all mode, requests with an Authorization header or session cookies are not cached, since they may contain personalized content. In bot-only mode this is less relevant since bots rarely send authentication.

synthesize_cache_control

When the origin does not include a Cache-Control header, PRISM adds one based on the configured TTL for that path. This helps downstream CDNs and browser caches respect PRISM's caching strategy.

error_ttl_secs

Error responses (HTTP 500+) are cached for a shorter duration to avoid serving errors for extended periods while still providing some protection against repeated failing renders. Set to 0 to disable error caching entirely.

vary

Use vary when the same path produces different rendered HTML depending on a request header — most commonly Accept-Language for multilingual SSR.

When configured, PRISM does two things for every header in the list:

  1. Fragments the cache key so that requests differing only in the header value are stored as separate cache entries.
  2. Forwards the header value to Chrome via setExtraHTTPHeaders so the SSR can actually produce variant-specific HTML. Without this, vary would just multiply identical cache entries — so PRISM does both atomically.
[cache]
vary = ["accept-language"]

Header names are case-insensitive. Header values are used as raw strings — en-US and en-us are stored as different variants. Pre-normalize at your CDN or reverse proxy to avoid cache fragmentation; for example, collapse the browser default Accept-Language: en-US,en;q=0.9 to a single primary tag like en before forwarding to PRISM.

Default is empty ([]) — no vary, one cache entry per path. Leave it empty for single-language sites.

:::tip Why not vary on every header by default? Each unique combination of vary values multiplies the cache footprint. Defaulting to vary on, say, Accept-Language would explode cache size for sites that don't actually serve language-varied HTML. Better to opt in. :::

:::warning Vary headers and bot/CDN behavior Bots typically don't send Accept-Language, so they all share one variant — fine for SEO. But CDN caches in front of PRISM must also vary on the same header, or they'll serve the wrong language. Configure Vary: Accept-Language on your CDN to match. :::

Example Use Cases

E-commerce site with mixed content freshness

[cache]
enabled = true
max_entries = 50000
max_memory_bytes = 536870912 # 512 MiB
default_ttl_secs = 1800

[[cache.rules]]
pattern = "/products/**"
ttl_secs = 3600

[[cache.rules]]
pattern = "/categories/**"
ttl_secs = 7200

[[cache.rules]]
pattern = "/blog/**"
ttl_secs = 86400

Development / debugging with caching disabled

[cache]
enabled = false

Aggressive caching for mostly-static site

[cache]
enabled = true
max_entries = 100000
default_ttl_secs = 86400
grace_period_secs = 3600
error_ttl_secs = 60