Skip to content

Cache

Rendered sections are fragment-cached in published mode. Invalidation works by cache tag, so caching only happens on a taggable store — one whose driver extends Laravel's TaggableStore. On any other driver the tag probe fails and FilamentCraft transparently falls back to no-cache: pages render fresh, nothing breaks, and you get no speedup.

Taggable — caching worksNot taggable — silently uncached
redis, memcached, apc, arrayfile, database, dynamodb

file is Laravel's default, so out of the box you get no fragment caching until you point this at a taggable store.

php
'cache' => [
    'enabled' => true,
    'store' => null,     // shipped default: the app's default cache store
    'ttl' => 3600,       // fragment lifetime in seconds
    'tag_prefix' => 'fc',
],

'store' => null (the shipped default) uses the application's default cache store. If that isn't a taggable one, point this at a store that is — for example 'store' => 'redis'.

Draft renders are never fragment-cached: the editor re-renders from the DraftStore on every request, so what you see is always current. (The DraftStore is itself cache-backed, keyed per user and template — it just isn't part of the fragment cache.)

Invalidation is per site

Every cached fragment is tagged site:{id}. Publishing a template or region — or saving site settings — flushes that one tag, which evicts all cached fragments for the site; there is no per-template granularity. Invalidation is wrapped in a try/catch, so a cache hiccup never blocks a publish.

Opting a section out: cacheable()

The render path checks YourSection::cacheable() before touching the cache; return false for sections whose output depends on per-request state:

php
public static function cacheable(): bool
{
    return false;
}

Built-ins that opt out: Countdown (the remaining time and expired state are computed server-side at render time), the commerce sections (Cart, Checkout, ProductListing, ProductDetail), and Header — but only while a custom localeUrlsUsing() resolver is registered, because host locale URLs are path-dependent and the fragment cache is per locale, not per path.

Cache-key composition

A fragment's key hashes the section's settings and blocks, plus the render color scheme and render context, and appends the locale and the site's theme version:

{tag_prefix}:section:{siteId}:{sectionId}:{sha1(settings+blocks+scheme+context)}:{locale}:{themeVersion}

That composition is the "why didn't my change appear" explainer: any settings edit, locale, theme-token change (theme version bumps), or color-scheme switch produces a new key automatically — stale output within the TTL can only come from data the key doesn't see (e.g. an external API a section reads at render time).

tag_prefix prefixes the key, not the tags

tag_prefix namespaces the cache keys so several apps can share one Redis instance. The invalidation tag is always site:{id}, unprefixed — if two apps share a store and a site id, flushes cross over; give them separate Redis databases instead.