Skip to content

Browser Caching in WordPress: How to Set Cache-Control and Expires Correctly

4 min read

Browser Caching in WordPress: How to Set Cache-Control and Expires Correctly – WordPress browser caching

If every returning visitor downloads the same logos, CSS files and scripts all over again, you’re paying for bandwidth and time on resources that haven’t changed one bit. This is where WordPress browser caching comes in: you tell the browser to keep these files locally, so on the next visit it pulls them straight from disk instead of from the server. The page loads almost instantly, the server breathes easier, and the site feels noticeably faster without changing a line of content.

What WordPress browser caching actually means

When someone opens your site, the browser fires off dozens of requests: fonts, images, stylesheets, scripts. Without instructions, it asks for them again on every page. With the right headers, it gets a clear message: “this file is valid for another 30 days, stop requesting it for nothing.”

In practice, you move part of the traffic off the server and onto the visitor’s device. It doesn’t help the first visit, when everything downloads once anyway, but it turns the second, third and every internal navigation into a much faster experience.

Cache-Control vs Expires: what’s the difference

Expires is the old method. You give the browser a fixed date until which the file is valid, for example “August 15, 2026, 12:00”. It works, but it depends on the device’s clock being correct and it’s harder to maintain.

Cache-Control is the modern standard and you’ll prefer it almost every time. Instead of a fixed date, you work with a relative duration and clear directives:

  • max-age=2592000 — the file is valid for 30 days (the value is in seconds);
  • public — it can be stored by proxies or a CDN, not just the browser;
  • immutable — tells the browser the file won’t change until it expires, so it won’t revalidate it;
  • no-cache — it can be stored, but must be checked with the server before use.

When you set both headers, Cache-Control wins over Expires. So the advice is simple: rely on Cache-Control and keep Expires only as a safety net for very old browsers.

Diagram of WordPress browser caching layers: HTTP request, Cache-Control header, local storage and reuse from cache.WordPress Browser CachingFirst HTTP requestCache-Control headerBrowser stores locallyRepeat visit from cacheRevalidation with ETagmax-age expiry
How a file flows through WordPress browser caching, from the first request to reuse from cache.

How to set caching correctly in WordPress

You have three routes, depending on how much control you want and which server you run.

1. From the .htaccess file (Apache or LiteSpeed)

The most direct method on most cPanel hosts. You add rules with mod_expires and mod_headers that set Cache-Control for each file type. It’s fast, but any syntax mistake can take your site down, so back up first.

2. Through a caching plugin

LiteSpeed Cache, W3 Total Cache or WP Rocket add these headers with a single checkbox. It’s the option I recommend to clients who don’t want to touch server files: you control everything from the WordPress dashboard and avoid syntax errors.

3. From the server or CDN configuration

If you use Nginx or a CDN like Cloudflare, the cleanest approach is to set the headers there, as close to the visitor as possible. Watch out: Cloudflare can override your rules, so check which “Browser Cache TTL” policy is active.

What expiry to choose for each file

Not every file deserves the same lifetime. The golden rule: the less often a file changes, the longer you cache it.

  • Images, fonts, logos: six months to a year — they rarely change;
  • CSS and JavaScript: about one month, ideally with “versioning” in the file name (e.g. style.css?ver=1.4) to force a reload on updates;
  • HTML: a few minutes or none at all — content changes often and you don’t want to serve stale pages.

Here’s the classic trap: if you set long lifetimes on CSS and JS without versioning, visitors stay stuck with the old styling after you make changes. That’s exactly why serious plugins add a version parameter to every file automatically.

How to check that browser caching really works

Don’t rely on “I added the rules, done.” Open DevTools in Chrome (the Network tab), reload the page and look at the Size column: files served from cache show up as “(memory cache)” or “(disk cache)”. You can also inspect the response header to confirm the real Cache-Control value.

For the full picture, run the page through PageSpeed Insights — if the “Serve static assets with an efficient cache policy” warning is gone, you’re on the right track. How the HTTP cache works is explained very clearly in the web.dev guide.

Browser caching is just one piece of the puzzle and works best alongside site speed optimization: compression, WebP images and a page cache on the server. If you want to know exactly what’s slowing you down, ask us for a free audit and we’ll show you in numbers where you lose seconds.

Conclusion

Browser caching is one of the cheapest speed improvements you can make: a few correct headers and your regular visitors get pages that load instantly. Choose Cache-Control as your main method, give static files long lifetimes, keep the HTML fresh, and always check the result right in the browser. It’s little effort for a gain you feel on every return visit.