CDN and edge caching
CDN and edge caching
1) Objectives
CDN (Content Delivery Network) reduces latency and load on origin: caches static and conditionally dynamic content on edge nodes, provides scale, stability and security (DDoS/WAF), adds edge logic (rewriting responses/requests, authentication, A/B).
2) Cache model and keys
Ключ кеша = `scheme + host + path +?(selected query params) + headers (Vary)`
Recommended:- Normalize query ('utm _' exclude, leave 'v', 'lang', 'country', etc.).
- Minimize'Vary '(for example,' Vary: Accept-Encoding, Accept-Language '), avoid' Vary: '.
- For API - key from route + version identifier (semver, hash, build id) + necessary query/headers (for example, 'X-Tenant').
- For personalized pages - edge-segmentation (by cookie/geo) or Skip-Cache.
3) TTL policies and headers
Base headings:- `Cache-Control: public, max-age=300, s-maxage=3600, stale-while-revalidate=60, stale-if-error=300`
- 'Surrogate-Control '(if supported) is a separate policy for CDNs other than the browser.
- 'ETag '/' Last-Modified '- conditional requests (304) and traffic savings.
- For private: 'Cache-Control: private, no-store', if not cached.
- APIs that allow cache: 'Cache-Control: public, s-maxage = 60' + version key.
Recommended approach: "eternal" resources (with fingerprint in the file name) → 'max-age = 31536000, immutable'; "pages/JSON" → short TTL + SWR.
4) Disability: purge/soft-purge
Purge by URL: pointwise.
Purge by tag/key: group purges (use 'Surrogate-Key: products: 42 category: food').
Soft-purge: marks content "outdated," edge gives stale until a new version is received.
"Warm" warming up: after the deploy, pull the main pages from the regions.
5) Edge performance patterns
Stale-While-Revalidate: quick response with "outdated" copy + background update.
Prefetch of critical resources (preload, preconnect, dns-prefetch).
Compression: gzip/br (for text), zstd if CDN is supported.
HTTP/2/3 (QUIC): multiplexing and less latency.
TLS session resumption and OCSP stapling on the perimeter.
6) Images and videos
Image optimization at edge: resize/format negotiation (`Accept: image/avif,webp`), авто-WebP/AVIF, DPR-варианты.
Lazy-load и responsive (`srcset`, `sizes`).
Video: HLS/DASH, fragmented MP4, origin-shield (central cache) to reduce storms.
Thumbnail services and signed URLs for private images.
7) Perimeter security
WAF: OWASP rules, country/ASN blocking, rate-limits with key (IP + cookie + token).
DDoS: L3/4 scrubbing, L7 checkers, JS challenges/turnstile.
Signed URLs/cookies for private resources (video/reports): TTL + HMAC/EdDSA.
Geo-fencing and compliance (for example, banning regions).
8) Edge-compute (logic at the edge)
Cases:- Personalization without breaking cache: segments (A/B), geo, language on edge, and content is cached.
- Rewriting answers/titles, redirects, AB splits.
- Token-based authentication: JWT signature verification, key binding.
- Canary by cookie/percent: part of the traffic to the new backend.
Examples of technology include Cloudflare Workers/Durable Objects, Fastly Compute @ Edge, AWS Lambda @ Edge.
9) Multi-CDN and global perimeter
Reasons: coverage, SLA, cost, regional restrictions, isolation of incidents.
GSLB/Traffic Steering: on geo/latency/real errors; health-checks from multiple vantage points.
Single key/header scheme (Surrogate-Key), synchronized purge rules.
Origin-shield is common to all CDNs so as not to "hit" origin with disabilities.
10) Logging and metrics
Collect:- Hit ratio (cache, CDN → edge/origin), byte hit ratio.
- Latency p50/p95/p99, error-rate by code/route.
- Origin fetches: RPS/bytes/errors (protection against redundant misses).
- Regional charts (by POP/ASN/country).
- Integrate with Observability: Prometheus (pull via exporters), Grafana/OTel (push from edge logs).
11) SEO и SPA/SSR
SEO pages with SWR and short TTL are fast and fresh.
Sitemap/robots - we cache for a long time, but allow soft-purge.
Service Worker: offline caching, prefetch of critical paths, targeted updates.
12) Sample configurations and headers
12. 1 Cache-Control profiles
Static with fingerprint:
Cache-Control: public, max-age=31536000, immutable
HTML/SSR:
Cache-Control: public, max-age=60, s-maxage=600, stale-while-revalidate=60, stale-if-error=600
Surrogate-Control: max-age=600, stale-while-revalidate=120
API (cached storefront):
Cache-Control: public, s-maxage=60
Vary: Accept-Encoding
12. 2 NGINX (origin) - query/headers normalization
nginx map $arg_utm_source $utm_skip { default 1; "" 0; }
map $args $normalized_args {
default "";
"~(^ &)v=([a-z0-9]+)(& $)" "v=$2";
}
proxy_cache_key "$scheme://$host$request_uri?$normalized_args";
add_header Surrogate-Key "product:{{id}} category:{{cat}}";
12. 3 Fastly VCL - soft-purge and keys
vcl sub vcl_recv {
set req. hash += req. http. host req. url. path;
set req. hash += querystring. decode(req. url, "v,lang");
if (req. method == "PURGE") {
if (req. http. Fastly-Soft-Purge) { softpurge; } else { purge; }
return (synth(200, "purged"));
}
}
sub vcl_deliver {
set resp. http. Surrogate-Key = "product:42 category:food";
}
12. 4 Cloudflare Workers - Signed URLs
js export default {
async fetch(req, env) {
const url = new URL(req. url);
if (url. pathname. startsWith("/private/")) {
const token = url. searchParams. get("token");
if (!token! verify(token, env. SIGNING_KEY)) return new Response("Forbidden", { status: 403 });
}
return fetch(req);
}
}
12. 5 Lambda @ Edge - Geo Options
js exports. handler = async (event) => {
const req = event. Records[0].cf. request;
const country = req. headers['cloudfront-viewer-country']?.[0]?.value 'US';
if (country === 'DE') req. headers['accept-language'] = [{ key:'Accept-Language', value:'de' }];
return req;
};
13) Private data and API
Never cache private responses without key isolation (per-user/per-token).
Use Signed Cookies/Headers and'Vary: Authorization'only with strict control (otherwise - cache-bust).
Safe alternative: separate the public layer (cached) and private inclusions (ESI/edge composition).
14) Geo/content rules
Licensing restrictions: geo-deny on edge, placeholders instead of blocking origin.
Age/regulatory banners - render on edge (do not punch cache).
15) Anti-patterns
'no-cache, no-store'for the entire site → loss of CDN effect.
'Vary'on unstable headers (for example,' User-Agent ') → cardinality.
Clear the entire cache on each release.
Short TTLs without SWR → storm to origin.
Personal pages are cached without segmentation/token keys.
Lack of origin-shield → multiple parallel misses.
16) Implementation checklist (0-45 days)
0-10 days
Categorize resources: immutable/HTML/API.
Enable gzip/br, HTTP/2/3, query normalization, 'Surrogate-Key'.
Enter SWR/IFE and base purge.
11-25 days
Edge-image optimization (resize/format), origin-shield.
Signed URLs for private media, WAF/DDoS profiles.
Dashboards: hit ratio, origin fetches, p95 by POP.
26-45 days
Multi-CDN or GSLB strategy, canary weights on the perimeter.
Edge-compute for segmentation/AB/geo, soft-purge by keys.
Auto-warming and purge integration in CI/CD.
17) Maturity metrics
Byte hit ratio ≥ 85% for static, ≥ 60% for HTML/conditional dynamics.
Origin RPS stable at peaks (no "storms").
p95 TTFB reduced by ≥ 30% across major regions.
% of stale responses for incidents> 90% (user barely noticed).
Complete automation of purge keys in release pipelines.
18) Conclusion
The effective CDN circuit is keys/TTL/options, disability discipline, and edge logic. Add SWR/IFE, origin-shield, media optimization, and strong security (WAF, signed URLs). Standardize metrics and integrate purge into CI/CD - and you get a fast, economical and stable perimeter, ready for peak loads and black swans.