From harness-claude
Optimizes CDN caching: cache keys, Vary headers, Surrogate-Control, tag-based purging, s-maxage TTLs, ESI. Use for low hit ratios, slow purges, TTL separation, fragmentation.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Master CDN-specific caching mechanics — cache key composition, Vary header impact, Surrogate-Control directives, tag-based instant purging, edge TTL management with s-maxage, and edge-side includes for granular partial caching.
Designs and optimizes CDN architectures: tiered caching, origin shielding, edge compute, cache hit ratio optimization, multi-CDN strategies, geographic routing. For high TTFB, origin overload, low cache hits, global apps.
Guides designing CDN architectures, caching strategies, and global content distribution. Covers cache hierarchies, origin shielding, invalidation, and edge optimization.
Guides Netlify CDN caching: Cache-Control headers, stale-while-revalidate, cache tags, on-demand purges, durable cache, vary keys, and Next.js ISR patterns.
Share bugs, ideas, or general feedback.
Master CDN-specific caching mechanics — cache key composition, Vary header impact, Surrogate-Control directives, tag-based instant purging, edge TTL management with s-maxage, and edge-side includes for granular partial caching.
Separate CDN TTL from browser TTL. Use s-maxage for CDN and max-age for browser:
# CDN caches for 1 hour, browser caches for 5 minutes
Cache-Control: public, max-age=300, s-maxage=3600
# CDN caches for 1 day, browser must always revalidate
Cache-Control: public, max-age=0, s-maxage=86400, must-revalidate
s-maxage only applies to shared caches (CDN, proxy). Browsers ignore it and use max-age.
Configure Surrogate-Control for CDN-specific behavior. Some CDNs support Surrogate-Control headers for directives that should not reach the browser:
# Fastly/Varnish Surrogate-Control
Surrogate-Control: max-age=86400
Cache-Control: no-cache
# CDN caches for 1 day; browser always revalidates
# CDN strips Surrogate-Control before forwarding to browser
Implement tag-based cache purging. Tag individual responses with cache keys for targeted invalidation:
# Tag responses with content identifiers
Surrogate-Key: article-12345 section-news author-jane homepage
# (Fastly)
Cache-Tag: article-12345, section-news, author-jane, homepage
# (Cloudflare)
# Purge by tag (all responses tagged with "article-12345")
# Fastly API:
POST /service/{id}/purge/article-12345
# Cloudflare API:
POST /zones/{id}/purge_cache
{"tags": ["article-12345"]}
Optimize cache key composition. The cache key determines what is considered a unique response. Audit and simplify:
# Default cache key (often too broad):
scheme + host + path + query-string + cookies + accept-encoding + accept-language
# Optimized cache key:
scheme + host + path + sorted-query(keep: page, q; strip: utm_*, fbclid)
# CDN configuration (Cloudflare example):
# Cache Rules → Custom cache key → Query string: Include specific
Configure Vary header correctly. The Vary header tells caches to store separate versions based on specific request headers:
# Good: vary on encoding (mandatory for compressed content)
Vary: Accept-Encoding
# Acceptable: vary on encoding and language
Vary: Accept-Encoding, Accept-Language
# Bad: vary on everything (disables caching)
Vary: *
# Bad: vary on Cookie (per-user cache = 0% hit rate)
Vary: Cookie
Each unique combination of Vary header values creates a separate cache entry. Vary: Accept-Encoding typically creates 2-3 variants (br, gzip, identity). Adding Accept-Language with 10 languages creates 20-30 variants.
Implement cache warming after purge. After a cache purge or deploy, pre-populate the CDN cache:
# Warm cache for top pages from multiple PoP regions
URLS=(
"https://example.com/"
"https://example.com/products"
"https://example.com/about"
)
for url in "${URLS[@]}"; do
curl -s -o /dev/null -w "%{http_code} %{time_total}s %{url_effective}\n" "$url"
done
Use soft purge instead of hard purge. Soft purge marks content as stale rather than deleting it. The stale content is served while the CDN fetches a fresh copy from origin:
# Hard purge: content deleted, next request goes to origin (cache miss)
# Soft purge: content marked stale, served while revalidating (no miss)
# Fastly soft purge:
PURGE /path HTTP/1.1
Fastly-Soft-Purge: 1
The ideal cache key includes only information that changes the response content. Including extraneous information (tracking parameters, session cookies) creates unique cache entries for identical content.
Common cache key pollution sources:
utm_source, utm_medium, utm_campaign) — strip from cache key_=timestampSec-CH-UA, Sec-CH-UA-Mobile create device-specific entriesESI allows a CDN to assemble a page from multiple cached fragments, each with its own TTL:
<!-- Page template (TTL: 5 minutes) -->
<html>
<header>
<esi:include src="/fragments/nav" />
</header>
<main>
<esi:include src="/fragments/article-12345" />
</main>
<aside>
<esi:include src="/fragments/trending" />
</aside>
</html>
<!-- /fragments/nav (TTL: 1 hour — rarely changes) -->
<!-- /fragments/article-12345 (TTL: 1 day — content-hashed) -->
<!-- /fragments/trending (TTL: 5 minutes — frequently updated) -->
The New York Times uses Fastly's Surrogate-Key headers to tag every article response with its article ID, section, author, and homepage status. When an editor updates an article, the CMS sends a purge request for that article's tag. Fastly purges all cached variants of that article across all global PoPs in under 150ms. Without tag-based purging, they would need to purge by URL — but each article may be served at multiple URLs (canonical, AMP, mobile) and embedded in section pages and the homepage. Tag-based purging handles all these variants with a single API call.
Shopify handles 80,000+ requests per second during flash sales using a Varnish-based CDN configuration with grace mode. During normal operation, product pages are cached with a 60-second TTL. During flash sales, they extend the grace (stale-while-revalidate) period to 300 seconds. If the origin becomes slow or unavailable under load, the CDN continues serving stale content while attempting to refresh. This prevents the thundering herd problem: instead of all cache misses hitting origin simultaneously, a single background refresh updates the cache while all other requests are served from stale.
Vary: * (disables caching entirely). The * value tells caches that the response varies on everything — effectively uncacheable. If you see Vary: * in responses, it is a misconfiguration. Identify the actual varying dimensions and list them explicitly.
Including Cookie in the cache key for public content. If the page content is the same for all users, cookies should not be part of the cache key. Each unique cookie value creates a separate cache entry, resulting in near-0% hit rates. Use private caching or client-side personalization instead.
Purging the entire cache instead of targeted paths. A full-zone purge forces every resource to be re-fetched from origin. For a site with 100,000 cached resources, this creates a thundering herd on origin. Use path-based or tag-based purging to invalidate only what changed.
Not separating browser TTL from CDN TTL. Without s-maxage, the CDN uses max-age — meaning the browser and CDN have identical caching behavior. A 5-minute browser TTL makes sense (users see fresh content), but the CDN should have a longer TTL (1 hour) to maximize edge cache hits.