Background
Archive
Journal Entry

Caching Strategies for Website Performance (2026 Guide)

Documented
Capacity
8 MIN READ
Domain
Website Performance & Ops

The fastest request is the one you never make. Get caching right and returning visitors load your site in milliseconds, your server handles far more traffic without breaking a sweat, and your hosting bill stays predictable. Get it wrong and you serve stale prices, logged-out users see someone else’s dashboard, or a deploy goes live and nobody sees the changes for an hour. Good caching strategies for website performance sit across four layers, and most teams only think about one of them.

Here is how the whole stack fits together, the headers that do the actual work, and the invalidation patterns that stop caching from becoming a liability.

The Caching Layers, and How They Stack

Every request to your site can be intercepted at four points before it ever reaches your application code:

  1. Browser cache — the visitor’s own device stores assets locally, so a repeat visit doesn’t touch the network at all.
  2. CDN / edge cache — a network of servers close to the visitor stores copies of your pages and assets, so requests never have to travel back to your origin server.
  3. Application cache — your app stores the result of expensive operations (rendered pages, API responses) in memory or a fast store like Redis.
  4. Database cache — query results get cached so the database isn’t recalculating the same aggregate every time.

Requests hit these layers in order. Browser cache first, then CDN, then application, then database. If a layer has a valid cached copy, everything downstream never gets touched. This is why page speed gains from caching compound — a well-cached static asset never even reaches your server, let alone your database.

For most small and medium business sites, the browser and CDN layers do 90% of the work. Application and database caching matter more once you’re running dynamic dashboards, search, or anything computed per-request.

Cache Headers That Actually Work

HTTP gives you a small set of headers that control all of this. Most performance problems come down to using the wrong one, or none at all.

Cache-Control is the header that matters most. It tells browsers and CDNs how long content is valid and under what conditions:

  • Cache-Control: public, max-age=31536000, immutable — for versioned static assets (JS, CSS, images with a hash in the filename). Cache for a year; the file will never change because a new deploy gets a new filename.
  • Cache-Control: public, max-age=3600, stale-while-revalidate=86400 — for HTML pages that update occasionally. Serve the cached version instantly, but refresh it in the background so the next visitor gets the new copy.
  • Cache-Control: no-store — for anything containing personal data: account pages, checkout, authenticated API responses.
  • Cache-Control: private, max-age=0, must-revalidate — for content that’s user-specific but safe to store locally, just not shared across users at the CDN.

ETag gives each version of a resource a fingerprint. When a browser has a cached copy, it can ask “has this changed?” with the ETag instead of re-downloading the whole file. If nothing changed, the server replies with a tiny 304 Not Modified instead of the full payload.

Vary tells caches that the same URL can return different content depending on a request header — most commonly Vary: Accept-Encoding or Vary: Cookie. Get this wrong and a CDN will happily serve one visitor’s personalised content to the next visitor who hits the same URL.

stale-while-revalidate is the quiet hero of modern caching. It lets a cache serve a slightly outdated response immediately while fetching a fresh one in the background, so nobody ever waits on a cache miss.

A practical recipe by page type:

Content typeHeaderWhy
Hashed JS/CSS/imagespublic, max-age=31536000, immutableFilename changes on every deploy, so cache forever
Marketing HTML pagespublic, max-age=300, stale-while-revalidate=86400Fresh enough, never a stale-feeling wait
API responses (public data)public, max-age=60, stale-while-revalidate=300Balances freshness with load reduction
Authenticated pages/APIprivate, no-storeNever cache anything user-specific at a shared layer
Fontspublic, max-age=31536000, immutableFonts almost never change once shipped

CDN Caching Strategy

A CDN stores copies of your content on servers distributed globally, so a visitor in Leeds isn’t waiting on a round trip to a server in Virginia. The strategic question is what to cache at the edge and for how long.

Static assets are the easy case — cache aggressively, invalidate rarely. The harder case is HTML and API responses that change but not on every request. Most CDNs, including Cloudflare, let you cache HTML at the edge with short TTLs and background revalidation, which gets you CDN-speed responses without serving genuinely stale content.

For dynamic, per-user content, the pattern that works is caching the page shell at the edge and hydrating personalised sections client-side, or excluding specific paths from the cache entirely using cache rules. Cloudflare’s cache rules let you set this per route: cache /blog/* aggressively, bypass cache entirely on /account/* and /api/checkout.

Purge strategy matters as much as caching itself. On deploy, you want to purge exactly what changed — not the entire cache, which causes a traffic spike to your origin as every cached asset gets requested fresh simultaneously. Targeted purges by URL or cache tag avoid that “thundering herd” problem.

Common Caching Mistakes

Over-caching dynamic content. Setting a long max-age on a page that shows different content per user is the single most common cause of “why is my site showing the wrong thing” support tickets.

Under-caching static assets. Serving your logo with max-age=0 means every single visitor re-downloads it, even though it hasn’t changed in eight months. If it has a hash in the filename, cache it for a year.

Breaking authentication. Caching a page that includes a login state (even indirectly, through a “Welcome, [Name]” header) without Vary or private can leak one user’s session data to another. This is a genuine security issue, not just a UX bug.

Ignoring query strings. By default, many CDNs treat /products?id=1 and /products?id=2 as different cache entries, and some treat every unique query string combination as new. If your tracking parameters (?utm_source=...) are appended inconsistently, you can end up with thousands of near-duplicate cache entries and a much lower hit rate than you’d expect.

Cache Invalidation Patterns

There’s an old joke that cache invalidation is one of the two hard problems in computer science. In practice, four patterns cover almost every real-world case:

Time-based (TTL). Set a max-age and let it expire naturally. Simple, predictable, but content can be stale for up to the TTL window.

Event-based. Purge specific URLs the moment content changes — a CMS publish webhook triggers a targeted cache purge. More complex to build, but content is fresh the instant it changes.

Versioned URLs. Append a hash or version number to the filename (app.a1b2c3.js). The URL itself changes when the content changes, so you can cache forever and never need to invalidate — you just stop referencing the old URL.

Purge APIs. Most CDNs, Cloudflare included, expose an API to purge by URL, by tag, or the entire zone. Wire this into your deploy pipeline so a release automatically invalidates exactly what changed.

For most SMB sites, the winning combination is versioned URLs for static assets (never invalidate, cache forever) plus a short TTL with stale-while-revalidate for HTML pages (self-healing, no manual purge needed for routine content changes).

Getting This Right Without a Dedicated Ops Team

Most businesses don’t have a platform engineer whose job is tuning cache headers. That’s the gap Fernside’s managed systems work fills — we configure caching correctly at build time and monitor it afterwards, so a marketing site update doesn’t accidentally cache someone’s account page, and a genuine content change doesn’t sit stale for a day because nobody purged it.

If you’re not sure whether your current site is caching correctly, that’s worth checking before it becomes a support ticket or a security concern.

Want a performance and caching audit of your current site? Get in touch and we’ll look at what’s cached, what isn’t, and what’s costing you speed or reliability. Our advisory service covers this as part of a broader technical review if you want the full picture.

Further Reading