Peak-Traffic Dispatcher Strategy for a Global Retailer
A global retailer runs AEM as a Cloud Service with a single publish tier serving three regional brands from one Dispatcher farm. During a flash sale, origin CPU hits 95%, average publish response time climbs from 180 ms to 2.4 s, and 30% of requests return 503. Dispatcher logs show a 12% cache hit ratio on HTML pages. Marketing recently enabled personalization on the homepage hero using a context-aware component that reads a geo cookie, and the team added Cache-Control: no-cache to all HTML responses to 'avoid stale pricing'. The CDN in front of Dispatcher honors origin headers. Traffic is 85% anonymous, 15% authenticated. The architect must restore stability before the next sale in two weeks and keep personalization for logged-in users.
1. Diagnose why the cache hit ratio collapsed and rank the contributing causes by impact.
Read the worked answer
Primary cause: blanket Cache-Control: no-cache on HTML. This forces the CDN and Dispatcher to revalidate or bypass cache for every HTML request, so the 85% anonymous traffic that could be cached never is. With origin already saturated, this is the dominant driver of the 503s.
Secondary cause: cookie-based personalization leaking into the cached variant. A context-aware hero that reads a geo cookie can fragment the cache if Vary: Cookie is set or if the response is cached per-cookie. That multiplies variants and lowers hit ratio even after headers are fixed.
Tertiary: single farm, no brand/region separation. Three brands sharing one farm means cache invalidation for one brand flushes or competes with the others, and a hot brand can evict the others' entries.
Ranking logic: fix the header policy first (biggest multiplier), then isolate personalization to uncached paths, then consider farm segmentation. The 12% hit ratio is consistent with 'only static assets cached, all HTML bypassed'.
2. Propose a caching and personalization architecture that keeps anonymous pages cacheable while preserving personalized hero content.
Read the worked answer
Split the page into cacheable shell + dynamic fragment.
- Anonymous HTML: remove
no-cache; useCache-Control: max-age=300, s-maxage=600, stale-while-revalidate=60for listing pages and shorter TTLs (e.g., 60s) for pricing surfaces. Pricing freshness is a TTL problem, not a no-cache problem. - Personalization via client-side or edge include: render the hero variant through an experience fragment fetched by a small JS call to a non-cached endpoint (
/content/...hero.json) keyed on user session, or use Edge Side Includes / CDN edge compute to assemble the personalized fragment. The HTML shell stays anonymous-cacheable. - Cookie hygiene: never set
Vary: Cookieon full pages; scope personalization cookies to the fragment endpoint path only. - Invalidation: use targeted cache invalidation (content activation triggers purge of affected paths) instead of TTL-only, so pricing updates propagate without global no-cache.
- Farm segmentation: one farm per brand (or at least per region) so invalidations and hot content don't cross-contaminate.
Expected outcome: anonymous hit ratio should rise well above 70%, origin load drops proportionally, and logged-in users still get personalized heroes through the fragment path.
3. What pre-sale validation would you require before declaring the fix safe?
Read the worked answer
- Load test at 3x observed peak against the new header policy, measuring origin CPU and p95 latency; confirm 503 rate near zero.
- Cache hit ratio measurement segmented by anonymous vs authenticated and by brand, to prove the 85% anonymous cohort is actually cached.
- Personalization correctness test: verify logged-in users see the right hero and that the fragment endpoint is not cached across users (check response headers and a two-user test).
- Invalidation test: activate a price change and confirm it appears within the agreed SLA (e.g., ≤2 minutes) without a global purge.
- Rollback plan: feature-flagged header config and a documented revert to the previous Dispatcher config.
- CDN behavior check: confirm the CDN honors the new
s-maxage/stale-while-revalidateand does not strip them.