Operations

Markdown

Performance tuning

Operator guide for keeping Public CMS API and admin paths fast: response cache, lean includes, queue workers, and Pulse/Health signals.

Public API response cache

Externa caches successful Public CMS API reads (REST and GraphQL) via PublicApiResponseCache.

FactDetail
FreshnessSynchronous collection version bump on write — cache misses immediately after publish/edit
TTLSafety net only (PublicApiResponseCache::TTL_SECONDS = 120) for orphaned payload keys
Global flushSettings → Performance → flush Public API cache (bumps a global epoch folded into every collection version)
StatusSame Performance page shows cache store, Redis reachability, queue driver, and public API epoch

When debugging stale public reads: confirm the write path bumped the collection, then flush Public API cache from Performance if you force-edited data outside normal writers.

include costs

Public item list/show responses are lean by default. Expanding files, users, or relations costs extra queries and payload size.

PracticeWhy
Prefer no include for list cardsKeep IDs; hydrate detail pages only
Add include=files only when the UI needs file objectsWithout it, image/file fields stay as stored IDs
Limit relation field names in includeDepth 1 only; nested items do not re-apply relation includes
Avoid spraying CSV tokens “just in case”Unknown tokens are ignored, but known ones still hydrate

See Public CMS API — Expand with include.

RelationInclude list prewarm

Core #112 tracks list-level batch prewarm in RelationIncludeHydrator to kill N+1 when many items include the same relations. Not shipped yet — until it lands, prefer fewer includes on large list pages or fetch detail pages with includes instead of hydrating every row.

Queues & Horizon

Async work (webhook delivery, zips, imports, AI attachments, Meilisearch / git export jobs) needs a real queue worker. Without it, HTTP stays snappy while background features stall and storage grows.

StackWorker
Full (Redis)php artisan horizon + Horizon
MinimalQUEUE_CONNECTION=database + queue:listen / queue:work — Minimal vs full

Do not use QUEUE_CONNECTION=sync in production — large zips/imports block requests. Scheduler must run every minute for scheduled publish and cleanup (Operations).

Reading Pulse for CMS hotspots

Dashboard → Health shows Pulse aggregates without embedding Livewire Pulse:

SignalWhat to check
exceptions_24hSpikes after deploys or bad public clients
slow_jobs_24hWebhook / import / zip jobs timing out
slow_queries_24hHeavy list filters, missing indexes, over-broad includes

Deep dive: /pulse (super-admin). Settings → Performance links Jobs / Pulse / Horizon when permitted. Full config: Pulse & Health.

Quick checklist

  1. Redis (or database queue) + Horizon/worker running in prod
  2. Scheduler every minute
  3. Public list endpoints without unnecessary include
  4. Performance flush after unusual cache suspicion
  5. Watch Health tab after traffic or content spikes