SysDesignPrep.com
Study guide 32 of 188

Updated 24 October 2026

CDNs and edge computing

How a content delivery network works, push vs pull, cache keys and TTLs, what to put at the edge, edge functions and KV, and the pitfalls of caching dynamic content.

Reading is half of it. See it used in a real interview.A strong candidate answers Design a URL Shortener turn by turn, drawing the design as they talk. Free, no sign-up.
Watch the walkthrough

Try it yourself, in a playground:CDN caching and hit ratioAdaptive bitrate streamingRendezvous hashingHTTP caching

A content delivery network is a set of servers placed near users (points of presence, PoPs) that serve cached copies of your content so requests do not travel to your origin. For static assets it removes most of your bandwidth and 50 to 200 ms of latency. Increasingly it also runs code, which turns the edge into a first tier of your application.

How a request flows

  1. DNS resolves your hostname to the CDN (a CNAME to the provider, or the provider's anycast IP).
  2. The user's request lands at the nearest PoP.
  3. The PoP checks its cache using a cache key (by default the URL, optionally plus headers such as Accept-Encoding or a cookie).
  4. On a hit, the PoP responds. On a miss, it fetches from the origin (or from a regional "shield" cache that many PoPs share, so the origin sees one miss instead of hundreds), stores the response according to its Cache-Control headers, and responds.

Origin shielding is worth naming: without it a global cache expiry produces one origin request per PoP, and a large provider has several hundred PoPs.

Pull versus push

Pull (origin pull) is the default: the CDN fetches from your origin on the first miss. No upload step, content is always available at the origin, and only requested content is cached. The first request in each PoP is slow.

Push means you upload content to the CDN ahead of time. Used for large files with predictable demand (a game patch, a video release) so the first user in every region gets a hit. Most systems pull; say push only for pre-warming a known launch.

What to cache and for how long

  • Immutable assets (JS, CSS, images with a content hash in the filename): Cache-Control: public, max-age=31536000, immutable. Cache forever; a new deploy has new filenames.
  • Public pages and API responses that are the same for everyone: short TTLs (10 s to a few minutes) with s-maxage for the CDN and max-age for browsers, plus stale-while-revalidate so a user never waits for the refresh.
  • Personalised responses: normally not cached at the CDN. If you must, the cache key has to include the user (a cookie or header), which destroys the hit rate. Better: cache the shell publicly and fetch the personal part separately.
  • Large media: always. Object storage as origin, CDN in front, signed URLs for private content.

Use Vary sparingly. Every header in Vary multiplies the cache entries; Vary: Cookie effectively disables caching.

Invalidation

CDNs offer purge by URL, by prefix, or by tag (surrogate key). Tag-based purge is the useful one: tag every response with the entity ids it contains (product-123, category-9), and when the product changes, purge the tag. Propagation to all PoPs takes seconds. For content that changes on a schedule, prefer a short TTL over purging: it is simpler and self-healing.

Versioned URLs avoid invalidation entirely: change the filename, and the old entry is simply never requested again.

Edge compute and edge storage

Providers now run functions at the PoP (Cloudflare Workers, Fastly Compute, Lambda@Edge, Vercel Edge Functions), with a replicated key-value store next to them (Workers KV, Fastly Config Store, Vercel Edge Config). Latency to that KV is single-digit milliseconds, and it replicates globally in seconds to a minute.

Good uses, each of which comes up in interviews:

  • Redirects and routing. A URL shortener serving code → URL from edge KV never touches the origin for the read path. See Design a URL Shortener.
  • Authentication and feature flags. Validate a JWT or read a flag at the edge and route accordingly.
  • A/B assignment and personalised caching. Decide the variant at the edge, then serve a cached variant page.
  • Rate limiting and bot filtering before traffic reaches the origin.
  • Response assembly. Fetch a cached shell and a small dynamic fragment and stitch them.

The constraints: no persistent connections to your database (or only through a regional proxy), limited CPU time per request, and the KV is eventually consistent, so it holds data that can be a minute stale, not the source of truth.

Failure modes to mention

  • Origin overload on expiry: many PoPs miss at once. Shielding, stale-while-revalidate, and staggered TTLs (jitter) address it.
  • Caching an error: a 500 gets cached and served for the TTL. Configure short or zero TTLs for error responses and stale-if-error to serve the last good copy.
  • Cache poisoning: an attacker gets a response with malicious content or a bad header cached under a public key. Keep the cache key strict, and never include unvalidated request headers in the response.
  • Private data at the edge: a personalised response cached publicly leaks one user's data to another. Set Cache-Control: private on anything user-specific.

Interview phrasing

"Static assets and media go through the CDN with immutable, hashed URLs. Public API reads get a 30-second s-maxage with stale-while-revalidate, tagged by entity so we can purge on write. Personalised responses bypass the CDN. For the redirect path I would run an edge function reading from edge KV, so p99 is under 20 ms globally and the origin only sees misses."

Cache keys and the traps in them

The cache key is the part people get wrong. By default it is scheme + host + path + (some or all of) the query string, and every additional dimension divides your hit rate.

  • Strip tracking parameters (utm_*, fbclid) from the key, or a shared link tears a hole in the cache.
  • Vary carefully. Vary: Accept-Encoding is fine. Vary: User-Agent splits the cache thousands of ways and is almost always a mistake; use a device-class dimension with three values if you must.
  • Cookies usually make a response uncacheable at the edge. Serve the shell without cookies and fetch personalised fragments separately, or key on a small normalised cookie subset.
  • Content-hash the filename for static assets (app.8f3ac1.js) and cache it for a year immutably. The name is the version, so invalidation never happens.

Stale-while-revalidate and origin protection

Two headers do most of the work of keeping an origin alive:

  • stale-while-revalidate=60: serve the stale copy immediately and refresh in the background. Users never wait for the origin.
  • stale-if-error=86400: if the origin is failing, keep serving the stale copy rather than an error page. This turns an origin outage into a slightly stale site for anything cacheable.

Add request collapsing (the edge sends one request to the origin for many simultaneous misses on the same key) and tiered caching (edge → regional shield → origin), and a cold cache after a purge stops being an outage.

Signed URLs and private content

Private objects can still be edge-cached if you sign carefully: sign a path with a short expiry, and configure the CDN to exclude the signature parameters from the cache key while still validating them. Otherwise every user gets their own cache entry and the hit rate collapses. For per-user content that genuinely cannot be shared, cache at the edge only in the user's own browser and use the CDN purely for transport (TLS termination close to the user, warm connections to the origin), which is still worth 50–100 ms.

Measuring

  • Hit ratio, by content type. Static should be >95 %; API responses depend entirely on your key design.
  • Offload: the share of bytes served without touching the origin. This is the number that maps to cost.
  • Origin requests per second during a purge: the spike that tells you whether request collapsing is working.
  • p95 latency by region, which is what the CDN is for in the first place.

Checklist

  • What is cacheable, its TTL, and the cache key.
  • Versioned or hashed asset names so invalidation is rare.
  • stale-while-revalidate / stale-if-error and request collapsing.
  • How private content is served.
  • Purge mechanism and how long a global purge takes.
  • Hit ratio and offload targets.

Questions people ask

What is a CDN?

A content delivery network (CDN) is a set of servers placed near users, called points of presence (PoPs), that serve cached copies of your content so requests do not travel to your origin. For static assets it removes most of your bandwidth and 50 to 200 ms of latency. Static content should reach a hit ratio above 95 %, and offload, the share of bytes served without touching the origin, is the number that maps to cost.

CDN vs edge computing: what is the difference?

A CDN serves cached copies of content from servers near users, while edge computing runs your code on those same servers. Providers such as Cloudflare Workers, Fastly Compute, Lambda@Edge and Vercel Edge Functions run functions at the PoP with a replicated key-value store next to them, which turns the edge into a first tier of your application. Edge code suits redirects, authentication, A/B assignment and rate limiting, but gets limited CPU time per request and no direct persistent database connections.

How does a CDN edge server handle a request?

The edge server at the nearest PoP checks its cache using a cache key, by default the URL, and responds directly on a hit. On a miss it fetches from the origin, or from a regional shield cache that many PoPs share, then stores the response according to its Cache-Control headers. Shielding matters because a large provider has several hundred PoPs, and without it a global cache expiry produces one origin request per PoP.

How do you manage a CDN cache?

Managing a CDN comes down to deciding what is cacheable, its TTL, its cache key, and how it is invalidated. Hash static asset filenames and cache them for a year as immutable, give shared public responses short TTLs with stale-while-revalidate, and keep personalised responses off the CDN. When an entity changes, purge by tag (surrogate key), which reaches all PoPs in seconds; for content that changes on a schedule, a short TTL is simpler and self-healing.

Push vs pull CDN: which should you use?

Use pull for most systems: the CDN fetches from your origin on the first miss, with no upload step, and only requested content is cached. The cost is that the first request in each PoP is slow. Push means uploading content to the CDN ahead of time, which is worth it for pre-warming a known launch with predictable demand, such as a game patch or a video release, so the first user in every region gets a hit.

Can a CDN cache personalised content?

Normally not, because the cache key would have to include the user, which destroys the hit rate. The better pattern is to cache the page shell publicly and fetch the personal part separately. Anything user-specific should carry Cache-Control: private, since a personalised response cached publicly leaks one user's data to another. For per-user content that cannot be shared, the CDN can still act purely as transport, terminating TLS close to the user, which is still worth 50 to 100 ms.