# CDN & Edge Caching > Serve cached responses from PoPs near users, sparing the origin. Frontend architecture guidance from fearchitect, written by Abas Turabli and last reviewed 2026-06-21. Source: https://fearchitect.com/topics/cdn-edge-caching Use it as reference for the task at hand. Before changing code, check this guidance against the codebase: where the code already makes a different, deliberate choice, flag the conflict instead of rewriting it. Library APIs move faster than this guide, so confirm exact signatures in the official docs linked at the end. ## Summary A CDN caches responses at Points of Presence (PoPs) worldwide. Requests hit the nearest PoP instead of the origin, cutting latency and origin load. Cache lifetime at the edge is governed by `Cache-Control: s-maxage`; surrogate keys let you purge by tag rather than URL. Content-hashed assets use `immutable` for forever-caching; mutable resources pair short TTLs with on-demand purge. ## Definition A CDN (Content Delivery Network) places reverse-proxy caches at Points of Presence (PoPs) — data centers distributed close to users. When a response is cached at a PoP, subsequent requests for that URL are served from memory in single-digit milliseconds rather than crossing the globe to the origin. The CDN identifies what to cache and for how long via `Cache-Control` response headers, specifically `s-maxage`, which targets shared caches and overrides `max-age` for them. ## Diagram ```mermaid graph LR A[User / Browser] --> B[Nearest PoP] B -->|HIT: s-maxage fresh| A B -->|MISS or stale| C[Parent PoP / Shield] C -->|still miss| D[Origin Server] D -->|response + Cache-Control| C C -->|fill PoP cache| B ``` Request flow: user → nearest PoP → optional shield PoP → origin. Hits return immediately; misses propagate up the hierarchy. ## Cache keys, TTLs, and invalidation - The **cache key** is URL + selected `Vary` headers (e.g. `Accept-Encoding`). Query strings are included by default. - `Cache-Control: s-maxage=N` sets the edge TTL; `max-age` controls the browser TTL independently. - **Surrogate keys** (Fastly) / **cache tags** (Cloudflare) attach logical labels to responses so you purge by tag, not URL. - `stale-while-revalidate=N` at the edge serves stale while fetching fresh in the background — zero-latency deploys. - Content-hashed filenames (`main.abc123.js`) plus `Cache-Control: public, max-age=31536000, immutable` remove the need to purge at all. - **Shield / tiered caching** collapses origin traffic: only one PoP fetches from origin per cache miss worldwide. ## Invalidation strategies | Strategy | Granularity | Latency to take effect | Best for | | --- | --- | --- | --- | | **TTL expiry (s-maxage)** | URL | Up to full TTL | Slowly changing content | | **On-demand URL purge** | URL | Seconds via API | Known URLs, post-deploy HTML | | **Surrogate-key / tag purge** | Tag group | Seconds via API | CMS pages sharing a tag | | **Content hashing + immutable** | Filename change | Instant (no purge needed) | JS, CSS, image assets | ## Watch out: Never cache HTML with long s-maxage HTML is the entry point. A stale HTML document references hashed asset URLs that may no longer exist post-deploy, breaking the page for every cached user. Set `s-maxage` to 60 seconds or less on HTML, or use on-demand purge triggered by your deploy pipeline. Reserve long TTLs for content-hashed static assets only. ## Key terms - **PoP (Point of Presence)**: A CDN edge data center geographically near users where responses are cached. - **s-maxage**: Cache-Control directive setting TTL for shared caches (CDNs); overrides max-age for them. - **Surrogate key**: A tag attached to cached responses (via header) enabling bulk purge by label, not URL. - **Cache key**: The lookup key — URL plus any selected Vary headers — that identifies a cached entry. - **Shield / tiered caching**: A designated PoP that absorbs origin traffic; other PoPs fill from it instead of the origin. ## Related topics - [Caching Strategies](https://fearchitect.com/topics/caching-strategies.md): Layer browser, CDN, and app caches to serve responses without re-fetching. - [Network Performance](https://fearchitect.com/topics/network-performance.md): Hint, prioritize, and pre-navigate to cut request latency. - [Edge Computing & Rendering](https://fearchitect.com/topics/edge-computing-rendering.md): Run code at CDN PoPs to cut latency before origin is hit. - [API Gateway (for Frontends)](https://fearchitect.com/topics/api-gateway.md): Single entry point that routes, authenticates, and rate-limits across services. - [Real-time: WebSockets vs SSE vs Polling](https://fearchitect.com/topics/realtime-websockets-sse-polling.md): Match the right real-time transport to your data-flow direction. - [CI/CD for Frontend](https://fearchitect.com/topics/ci-cd-frontend.md): Automated pipeline from commit to production with quality gates. ## Further reading - [MDN — Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) - [Cloudflare — Cache rules and cache keys](https://developers.cloudflare.com/cache/how-to/cache-rules/) - [Fastly — Surrogate keys (cache tagging)](https://www.fastly.com/documentation/guides/full-site-delivery/purging/working-with-surrogate-keys/) - [web.dev — HTTP cache](https://web.dev/articles/http-cache)