Operations
MarkdownPerformance tuning
Operator guide for keeping Public CMS API and admin paths fast: response cache, lean includes, queue workers, and Pulse/Health signals.
Related
Public API response cache
Externa caches successful Public CMS API reads (REST and GraphQL) via PublicApiResponseCache.
| Fact | Detail |
|---|---|
| Freshness | Synchronous collection version bump on write — cache misses immediately after publish/edit |
| TTL | Safety net only (PublicApiResponseCache::TTL_SECONDS = 120) for orphaned payload keys |
| Global flush | Settings → Performance → flush Public API cache (bumps a global epoch folded into every collection version) |
| Status | Same 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.
| Practice | Why |
|---|---|
Prefer no include for list cards | Keep IDs; hydrate detail pages only |
Add include=files only when the UI needs file objects | Without it, image/file fields stay as stored IDs |
Limit relation field names in include | Depth 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.
| Stack | Worker |
|---|---|
| Full (Redis) | php artisan horizon + Horizon |
| Minimal | QUEUE_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:
| Signal | What to check |
|---|---|
exceptions_24h | Spikes after deploys or bad public clients |
slow_jobs_24h | Webhook / import / zip jobs timing out |
slow_queries_24h | Heavy 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
- Redis (or database queue) + Horizon/worker running in prod
- Scheduler every minute
- Public list endpoints without unnecessary
include - Performance flush after unusual cache suspicion
- Watch Health tab after traffic or content spikes