Performance
Caching Strategy 101: Browser, CDN, and Server Explained Simply
How browser, CDN, and server caches work together so you can reason about freshness and performance.
Caching happens at several layers. Understanding each one helps you get speed without serving stale content where it matters.
Browser cache
The browser stores responses (HTML, CSS, JS, images) so repeat visits don’t re-download everything. You control it with Cache-Control headers: max-age (how long the browser can use the copy), and optionally stale-while-revalidate or no-cache. For static assets with hashed filenames (e.g. main.a1b2c3.js), use a long max-age (e.g. 1 year); the URL change when you deploy invalidates the cache. For HTML (or unhashed URLs), use a short max-age or no-cache so users get updates. Don’t cache personalized or sensitive responses in the browser; use private or no-store where needed.
CDN cache
A CDN sits in front of your origin and caches responses at the edge. The first request for a URL may hit the origin; subsequent requests get the cached copy from the edge until it expires (often driven by Cache-Control from the origin or by CDN rules). Use it for static assets and for cacheable HTML (e.g. public blog posts). Set Cache-Control from your server (or in your host/config) so the CDN knows how long to store the response. Purge or revalidate when content changes (e.g. after a deploy or when you publish a post). Many hosts and platforms (Vercel, Netlify, etc.) put a CDN in front by default; configure cache headers so the CDN behaves the way you want.
Server cache
On the server, you might cache database results, API responses, or rendered HTML (e.g. full-page cache, or cached fragments). That reduces load on the DB and speeds up response time. Invalidate or revalidate when data changes: time-based (revalidate every N seconds) or event-based (e.g. on publish, clear or update the cache). In Next.js, the route cache and fetch cache are server-side; use revalidatePath, revalidateTag, or fetch’s next.revalidate so updates show up when they should.
Putting it together
Static assets: long-lived browser cache, CDN in front, hashed URLs so deploys bust cache. HTML for public pages: short or medium cache at CDN and browser, revalidate on deploy or content change. API or personalized data: no cache or short TTL; avoid caching sensitive data at the edge. Document your choices (what’s cached, for how long, how you invalidate) so the team and future you can reason about freshness and performance.
Summary
Browser cache: control with Cache-Control; long cache for hashed assets, short or no-cache for HTML when freshness matters. CDN: cache at the edge using your headers; purge on deploy or content change. Server cache: cache DB/API or rendered output; invalidate on mutation. Use the three layers together so you get speed without stale content where it hurts.