Caching
Caching is opt-in per call — disabled by default. Reach for it on hot pages where the timeline doesn't change often: audit views, public profiles, dashboards rendered on every request. The simplest form wraps a paginate() in a TTL:
$entries = $record->timeline()->cached(ttlSeconds: 300)->paginate();
->cached(int $ttlSeconds)
Position in the chain: call before paginate() or get(). It has no effect on count() (which runs through get() un-cached internally — see /essentials/refining-the-timeline for why).
The cache lookup uses the active store, configured via cache.store (see Configuration knobs below).
cached(0) is a no-op. The TTL=0 short-circuit is intentional — useful for conditionally enabling cache via a flag without changing the call site:$record->timeline()
->cached(ttlSeconds: $cacheEnabled ? 300 : 0)
->paginate();
Cache key composition
Each cached paginate() call composes its key from the subject, the active filter set, and the page coordinates:
{prefix}:{model_class}:{key}:{filter_hash}:p{page}:pp{perPage}
Where:
{prefix}— thecache.key_prefixconfig value (default'activity-log').{model_class}— the subject's class name with\replaced by_(soApp_Models_Userrather thanApp\Models\User).{key}—$subject->getKey().{filter_hash}— a stringified hash of all builder filters:between, type allow/deny, event allow/deny, sort direction, source count.{page}and{perPage}— pagination params.
Changing any filter — ->ofType(...), ->between(...), ->sortByDateAsc() — produces a different key, so re-running the same builder with different chain state does not collide on a stale entry.
Invalidation
$record->forgetTimelineCache() invalidates only this subject's cached timeline pages. It tracks the keys it writes in a per-subject index entry ({prefix}:{model_class}:{key}:index) and forgets exactly those keys plus the index — sessions, queue locks, and other application caches in the same store are untouched.
Alternative: skip explicit invalidation and pick a TTL short enough that staleness is acceptable (e.g. 60 seconds for a high-traffic dashboard) and let entries expire naturally.
Configuration knobs
Short reference here; the full table lives on /essentials/configuration#cache.
| Key | Default | Effect |
|---|---|---|
cache.store | null (default cache) | Which Laravel cache store to use. |
cache.ttl_seconds | 0 | Reserved; not currently consulted by TimelineCache. The per-call ->cached($ttl) is the working knob. |
cache.key_prefix | 'activity-log' | Namespace for cache keys. |