CDN and static content for systems analysts
Contents:
Why CDN questions show up in SA interviews
A systems analyst at a product company lives at the boundary between frontend latency and backend load. The CDN sits exactly on that boundary. When an interviewer asks you to design a global product page, an image upload pipeline, or a video feed, the unspoken expectation is that you reach for a Content Delivery Network before a bigger origin server. Skip it and the rest of your design is fighting a problem the platform already solved.
CDN questions look trivial on the surface — "yeah, we cache static files closer to users" — and collapse the moment the interviewer pushes on invalidation, dynamic personalization, or cache hierarchy. A good answer treats the CDN as a programmable layer with its own consistency model, not a black box.
This post walks through the model interviewers expect at a Stripe, Netflix, or Airbnb SA loop: what edge caching does, how invalidation trades freshness for throughput, when to push logic to the edge, and the pitfalls that catch most candidates.
Load-bearing rule: the CDN is not free storage — it is a cache with a TTL and an eviction policy. Treat every static asset as a write to a distributed cache, and your design becomes coherent.
The mental model: origin, edge, client
There are three actors you should name out loud. The origin is the authoritative source — typically an S3 bucket, a GCS bucket, or a backend service behind a load balancer. The edge is a Point of Presence (PoP) operated by the CDN provider, sitting geographically close to users. The client is the browser or mobile app making the request.
A cold request flows client → nearest edge → origin → edge → client, and the edge stores the response. A warm request short-circuits at the edge and never touches the origin. The latency difference is significant in practice: a transatlantic round trip to a US origin from Sydney costs 180-250ms, while the equivalent edge hit from a Sydney PoP costs 5-20ms.
The mental model interviewers want is hierarchical. Modern CDNs run a two-tier topology: many edge PoPs for last-mile delivery, and a smaller set of shield or origin shield nodes that aggregate cache misses before they hit the origin. The shield matters because without it a viral asset would trigger thousands of simultaneous origin fetches — a thundering herd. With it, only one fetch per shield node reaches origin.
| Layer | Latency to user | Storage horizon | Job |
|---|---|---|---|
| Browser cache | 0ms | Per-device, small | Skip the network entirely |
| Edge PoP | 5-50ms | Hot working set | Serve 80-95% of requests |
| Origin shield | 30-80ms | Aggregated working set | Absorb edge misses |
| Origin (S3, backend) | 100-300ms | Authoritative, unbounded | Serve cold and uncacheable |
Most candidates draw two boxes — origin and edge — and miss the shield layer entirely. Drawing the third box is a cheap signal that you have shipped something behind a CDN before.
Cache invalidation: the actual hard part
The interviewer will press here. "You pushed a new logo. How do users see it?" There are three honest answers, and you should know all three.
Time-to-Live (TTL). Every cached response carries an expiry. The edge serves the cached copy until the TTL elapses, then revalidates with the origin on the next miss. TTLs are cheap to configure but slow to respond — a 24-hour TTL means yesterday's bug is still on the screen for some user in Lagos right now. Typical defaults: 1 year for hashed assets, 1 hour for HTML, 5 minutes for API responses.
Purge API. Every serious CDN exposes an endpoint to invalidate a URL or a set of URLs on demand. Cloudflare and Fastly purge globally in under 150ms; CloudFront historically took 60+ seconds. Purge is the right tool for incident response and for content that updates on an event (a published article, a price change), not for high-frequency invalidations — most providers throttle or bill aggressively past a few thousand purges per minute.
Versioned URLs. Instead of invalidating, you change the URL. The build pipeline emits /assets/app.7a3f9c.js, and the HTML references that exact hash. When you ship a new bundle, the hash changes, the URL changes, and the old version remains cached forever without conflict. This is the dominant pattern for JS, CSS, images, and fonts in modern frontends. It is also the only pattern that scales to millions of users without a purge bill.
// Webpack / Turbopack / Vite all do this by default in production
output: {
filename: '[name].[contenthash].js',
// produces: main.7a3f9c12.js
}A strong answer combines all three. Hashed URLs for JS, CSS, fonts, and images. Short TTL plus purge-on-publish for HTML and content APIs. Long TTL plus stale-while-revalidate for everything in between.
Sanity check: if your design requires invalidating a URL more than once a minute, you have built the URL pattern wrong. Re-hash, version, or add a query parameter.
Dynamic content and edge compute
The line between static and dynamic has been moving for a decade. Modern CDNs let you run code at the edge — Cloudflare Workers, Vercel Edge Functions, Fastly Compute, AWS Lambda@Edge — which means you can personalize, rewrite, authenticate, and even render full pages at the PoP.
Three patterns come up in interviews. The first is edge personalization: take a cached HTML response and inject user-specific fragments (a name, a country-specific price) at the edge using ESI or string substitution. The cached body stays shared; only the holes are filled per-request. This keeps cache hit rate at 90%+ while still personalizing.
The second is edge auth. You sit a Worker in front of the origin, validate a JWT or session cookie, and either serve from cache or return 401 without ever touching the origin. This collapses what used to be a backend round-trip into a 10ms edge check and reduces auth-service load by orders of magnitude.
The third is edge rendering (SSR at the edge). Frameworks like Next.js on Vercel render React on a Worker in the user's region, fetching data from a regional database read replica. The full page is delivered in under 100ms TTFB worldwide without a single multi-region database.
| Pattern | Origin requests | Cache hit rate | When to use |
|---|---|---|---|
| Pure static (hashed URLs) | 0 after first miss | ~100% | JS, CSS, images, fonts |
| Static HTML + edge personalization | Low | 85-95% | Marketing pages, content sites |
| Edge auth gateway | Auth on every request | N/A (auth layer) | API gateways, private content |
| Edge SSR | Per-request data fetch | 0% for HTML, ~100% for assets | Personalized apps, e-commerce |
| Origin SSR + CDN passthrough | All requests | 0% | Legacy apps, lift-and-shift |
The interviewer wants to hear you reason about which content category belongs in which pattern, not that you have memorized one specific framework.
Provider comparison
You will not be asked to name 12 providers, but you should be able to argue for a choice. The names that come up in US tech interviews:
Cloudflare dominates the mid-market and is the default for greenfield projects. Free tier, fast purge, mature Workers platform, sensible defaults. Weakness: enterprise pricing on bandwidth gets expensive at scale, and the free tier has gotchas around proxying large files.
Fastly is the engineering-first choice. VCL configuration language gives you near-arbitrary control at the edge, instant purge is bulletproof, and the Compute platform runs WebAssembly. Used by GitHub, Stripe, The New York Times. Weakness: steeper learning curve and no free tier.
AWS CloudFront is the default when you live in AWS. Tight integration with S3, ACM, Lambda@Edge, and WAF. Weakness: purge latency, less mature edge compute, and a UI that has not been redesigned since 2015.
Vercel wraps an edge network and adds developer experience tuned for Next.js and SvelteKit. Weakness: bandwidth pricing at scale, lock-in to framework conventions.
A useful answer names two providers and explains the tradeoff. Naming all six without an opinion signals you read a comparison post yesterday.
Common pitfalls
The first mistake candidates make is treating the CDN cache key as automatic. By default, most CDNs key by URL, ignoring query strings, cookies, and headers. That means a request to /dashboard with Cookie: user_id=42 will cache the response and serve it to user 43 on the next request. The fix is to either set Cache-Control: private for user-specific responses (which disables shared caching entirely) or to explicitly include the relevant cookie or header in the cache key. Get this wrong in a real system and you have a privacy incident.
The second pitfall is over-purging on every deploy. A new candidate will say "we purge all assets on deploy" and not realize that on a site with 50,000 assets this triggers a tidal wave of cold misses to origin, exactly when the new version is also serving traffic. The fix is content-hashed URLs — the old version stays cached, the new version is a different URL, and the origin only serves the new files as they are requested for the first time. Purge is for content updates, not for code deploys.
The third trap is ignoring the Vary header. If your origin returns different responses based on Accept-Encoding, Accept-Language, or User-Agent, you must tell the CDN via Vary. Otherwise the first response cached is served to everyone regardless of their headers. A particularly nasty version of this: serving a gzipped response to a client that did not request gzip, which then displays garbage.
The fourth is conflating CDN with caching strategy in the application. The CDN caches HTTP responses; the application has its own caches (Redis, in-memory, materialized views). A request that misses at the edge still hits the origin, which then can hit its cache hierarchy. Strong answers distinguish these layers explicitly. Confusing them on a whiteboard is the kind of thing that makes interviewers downgrade a senior candidate to mid.
The fifth mistake is assuming the CDN protects you from a hot-asset DDoS. It does, but only after the cache is warm. A viral link to an uncached URL can still trigger a thundering herd at origin without an origin shield, request coalescing, or a rate limiter. Most providers offer these; few candidates know to ask.
Related reading
- Cache strategies for systems analysts
- Capacity planning on the systems analyst interview
- API gateway vs BFF for systems analysts
- Backpressure on the systems analyst interview
- Background jobs for systems analysts
If you want to drill SA design questions like this, naildd has 1,500+ interview problems organized by exactly this pattern.
FAQ
What's the difference between a CDN and a reverse proxy?
A reverse proxy (nginx, HAProxy, Envoy) sits in front of your application server in a single data center and handles things like load balancing, TLS termination, and connection pooling. A CDN is a globally distributed network of reverse proxies operated by a third party, with the explicit job of caching content close to users. Most CDNs are reverse proxies under the hood — Cloudflare is a fleet of nginx and Pingora instances — but the geographic distribution and the cache-first behavior are what make it a CDN.
How do I cache an authenticated API response safely?
The honest answer is: in most cases, you don't cache it on the shared CDN cache. You set Cache-Control: private, max-age=60, which tells the browser it can cache the response for itself but tells the CDN to never store it. If you need shared caching for authenticated content, you key the cache by the auth token or by a derived user ID, accepting that you trade cache hit rate for personalization. Edge compute platforms make this easier because you can write the key-derivation logic in code.
What TTL should I set for HTML pages?
For a content site where pages rarely change but freshness matters when they do, the modern pattern is short TTL plus stale-while-revalidate. Set Cache-Control: public, s-maxage=60, stale-while-revalidate=86400. The edge serves fresh for 60 seconds, then serves stale for up to 24 hours while it revalidates with the origin in the background. Users always get a fast response; origin load stays low; freshness is bounded to about a minute.
How does HTTP/3 change anything for CDNs?
HTTP/3 runs over QUIC instead of TCP, which means a faster handshake on mobile networks with packet loss and no head-of-line blocking inside a single connection. CDNs are usually the first place HTTP/3 lights up because the edge sits closest to the client. It does not change your topology — origin, shield, edge, client — but it does mean a TTFB improvement of 50-150ms on flaky mobile links.
When should I avoid using a CDN entirely?
When the content is truly per-request and uncacheable — for example, a real-time trading dashboard where every tick is fresh and personalized — the CDN adds latency without removing origin load. In that case you still want a CDN for static assets (JS, CSS, fonts) but you bypass it for the data path entirely, going directly to your origin or to a WebSocket gateway. The other case is regulated environments where data residency rules forbid content from leaving a specific jurisdiction; some CDNs offer regional-only configurations to handle this, others do not.