Logo GH

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.

Contact

Get in Touch

Reach out with any questions or support needs.We are always ready to help!

Start Integration

Email is required. Telegram or WhatsApp — optional.

Your Name optional
Email optional
Subject optional
Message optional
Telegram optional
@
If you include Telegram — we will reply there as well, in addition to Email.
WhatsApp optional
Format: +country code and number (e.g., +380XXXXXXXXX).

By clicking this button, you agree to data processing.