Skip to main content

Browser Cache

Browser caching is about long-lived caching for static assets (CSS/JS/fonts/images) so repeat visits do not re-download the same files. The main rule: cache assets aggressively, but do not cache personalized HTML in the browser.

Goal: Cache Assets, Not HTML

Response TypeTypical Header StrategyWhy
Static assets (versioned)cache-control: public, max-age=31536000, immutableFast repeat views with no revalidation
Static assets (not reliably versioned)shorter TTL + revalidationAvoid serving broken assets after updates
HTML (public pages)usually short TTL / must-revalidateHTML freshness is handled by page cache + CDN rules
HTML (checkout/account/admin)no-storePrevent caching sensitive/personalized content

Versioning (Cache Busting)

Long cache TTL only works when you have a way to change the URL when the asset changes.

Common strategies:

  • Hashed filenames (best): app.2f3c1d.js
  • Query string versioning (common in WordPress): style.css?ver=2.1

If you deploy updates and do not bump versions, visitors can keep old CSS/JS and see broken layouts.

Implementation Examples

Nginx

nginx-static-asset-cache.conf
location ~* \.(css|js|woff2|png|jpg|jpeg|gif|svg|webp|avif|ico)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}

For checkout/account pages, consider no-store (route examples vary by site):

nginx-no-store-dynamic.conf
location ~* ^/(cart|checkout|my-account)/ {
add_header Cache-Control "no-store";
}

LiteSpeed / LSCache

LSCache can set browser cache headers for static assets.

  • LiteSpeed Cache -> Cache -> Browser

Cloudflare

Cloudflare can influence browser TTL. Prefer setting long TTL for static assets and keep HTML behavior governed by your cache rules/purges.

Verification

Check a static asset:

curl-check-static-asset-cache.sh
curl -I https://example.com/wp-content/uploads/hero.webp

You want to see a long max-age (and immutable when appropriate).

Check a sensitive route:

curl-check-checkout-no-store.sh
curl -I https://example.com/checkout/

Common Mistakes

MistakeWhat HappensFix
Caching HTML in the browser for dynamic routesStale or sensitive contentUse no-store for checkout/account/admin
Long TTL without versioningBroken CSS/JS after deploysUse hashed filenames or bump ?ver=
Multiple layers fight over headersConfusing behaviorDecide which layer owns headers (origin vs CDN)

What's Next