Front Runner Front End Web Development Blog

How to Use Browser Caching Properly

Learn how to use browser caching properly to speed up repeat visits, cut requests, and avoid stale files with simple, practical setup tips.

| June 9, 2026 | 8 min read

A slow first load is annoying. A slow second or third load is where users start judging you. That is exactly why learning how to use browser caching matters – it helps the browser keep static files locally so it does not need to fetch the same CSS, JavaScript, fonts, and images on every visit.

Browser caching is one of those performance wins that feels almost unfair once you understand it. Set it up well, and repeat page views get faster, bandwidth usage drops, and your server gets a bit of a breather. Set it up badly, though, and you end up shipping stale files while wondering why your latest stylesheet changes are apparently invisible to half the internet.

What browser caching actually does

When a browser downloads a file, it can store that file in its cache for later use. On the next page load, instead of requesting the same asset again, it may reuse the stored version if the caching rules say that is allowed.

This works best for files that do not change often, such as logos, font files, framework bundles, and compiled CSS. HTML is a different story. It usually changes more frequently and often should not be cached as aggressively, because it acts as the map that points to your latest assets.

So the basic idea is simple: cache static assets for longer, treat HTML more carefully, and make sure file changes are easy for the browser to detect.

How to use browser caching without breaking updates

The trick is not just enabling caching. The trick is enabling it in a way that still lets you ship changes safely.

If you tell browsers to keep a CSS file for a year, that can be great for performance. It can also be a minor disaster if the file changes but the filename stays the same. The browser sees no reason to fetch a fresh copy, so users keep the old one. That is where people start hard-refreshing like they are trying to repair the internet through sheer force.

The standard fix is cache busting. Instead of reusing the same filename forever, you change the filename when the file content changes. A common approach is adding a content hash to the filename, like app.8f3a2c.css. When you deploy a new version, the filename changes too, so the browser knows it is a different file and fetches it.

That combination is the sweet spot:

  • long cache lifetimes for static assets
  • short or cautious caching for HTML
  • hashed filenames for files that change

With that setup, you get speed without serving prehistoric CSS.

The headers that control browser caching

Browser caching is mainly controlled through HTTP headers. The two you will run into most often are Cache-Control and Expires, but Cache-Control does most of the heavy lifting on modern sites.

Cache-Control

Cache-Control lets you define how long a resource can be cached and who can cache it. For front-end assets, a common rule looks something like this:

“`http Cache-Control: public, max-age=31536000, immutable “`

Here is what that means in plain English. Public means the response can be cached by browsers and intermediary caches. Max-age sets the cache lifetime in seconds – 31536000 is one year. Immutable tells the browser that the file will not change during that period, which is ideal for versioned assets.

This is excellent for hashed CSS, JS, images, and fonts.

For HTML, you usually want a shorter window or revalidation. Something like this is more common:

“`http Cache-Control: no-cache “`

That does not mean “never cache”. It means the browser should check with the server before reusing the cached version. That is often what you want for documents that may change.

Expires

Expires is the older header. It sets a fixed date after which the resource becomes stale. It still appears in some setups, but Cache-Control is generally more flexible and more useful.

ETag and Last-Modified

These headers support revalidation. If a cached file may still be valid, the browser can ask the server whether it has changed. If not, the server responds with a 304 Not Modified, which avoids resending the full file.

That is helpful, but it is not as fast as avoiding the request altogether. For static, versioned assets, long max-age with hashed filenames is usually the stronger move.

Which files should you cache?

Not everything deserves the same strategy.

CSS, JavaScript, font files, icons, and images are the usual candidates for long-term caching if they are versioned properly. These files often change less frequently than the HTML that references them, and they make up a large chunk of repeat-load cost.

HTML should usually be treated more conservatively. The page document often changes when you deploy updates, publish new content, or alter asset references. If users get old HTML with references to old files, things can get messy quickly.

API responses are more nuanced. Some can be cached, some absolutely should not be, and some depend on whether the data is personalised or frequently updated. This is where “it depends” does a lot of work. If a response contains user-specific or sensitive data, be careful. Speed is nice, but not if you accidentally cache someone else’s dashboard. Bit awkward.

A practical setup most developers can use

If you want a sensible starting point, keep it simple.

Serve your HTML with a conservative cache policy, often no-cache or a very short max-age. Serve built assets like main.abc123.js and styles.def456.css with a long max-age and immutable. Make sure your build process generates new filenames when file contents change.

If you use a modern framework or bundler, this may already be handled for you. Vite, Webpack, Parcel, and similar tools commonly support hashed filenames out of the box. That means half the battle is making sure your server sends the right headers for those built files.

Server examples

The exact syntax depends on your server, but the principle stays the same.

Nginx

You might configure static assets to cache for a long time and HTML to revalidate more often.

“`nginx location /assets/ { expires 1y; add_header Cache-Control “public, max-age=31536000, immutable”; }

location / { add_header Cache-Control “no-cache”; } “`

Apache

With Apache, you would typically use mod_headers and mod_expires to set similar rules.

“`apache Header set Cache-Control “public, max-age=31536000, immutable”

Header set Cache-Control “no-cache” “`

These are not copy-and-paste magic spells for every project. Your file paths, hosting setup, and framework may differ. But they show the shape of a good configuration.

How to check if browser caching is working

Open DevTools, head to the Network tab, and reload the page. Look at your static assets and inspect the response headers. You should see Cache-Control values that match your intended strategy.

Then reload the page again and watch what happens. Some files may load from memory cache or disk cache. Others may show 304 responses if they are being revalidated. If every asset is still downloading in full on repeat loads, something is off.

It is also worth testing after a deployment. If you changed your CSS and users still receive the old file, your cache busting setup is probably the issue, not caching itself.

Common mistakes

The biggest mistake is giving long cache lifetimes to files with fixed names. If your site serves app.css forever and that file changes regularly, users will eventually get stuck on an outdated version.

Another common issue is treating HTML the same as static assets. A one-year cache on your homepage is not a bold optimisation strategy. It is more of a cry for help.

Developers also sometimes rely too heavily on ETags without using versioned filenames. Revalidation is useful, but avoiding unnecessary requests entirely is usually better for static files.

And then there is the CDN layer. If you use one, remember that browser caching and CDN caching are related but separate concerns. You may need to configure both. Otherwise, you can end up in the fun situation where the browser is behaving perfectly and the CDN is serving old content like it is preserving a historical archive.

When aggressive caching is worth it

If your site has a lot of repeat traffic, browser caching can make a noticeable difference. Dashboards, documentation sites, SaaS products, blogs, and ecommerce front ends all benefit because users often navigate through multiple pages that share the same assets.

For tiny one-page sites, the gains may be smaller, though still worthwhile. If your asset payload is already very lean, caching will help less than fixing oversized images or bloated JavaScript. Performance work is rarely one single trick. Browser caching is effective, but it is part of the system, not the whole system.

A good rule is this: cache anything static and versioned aggressively, cache HTML carefully, and always test the update path before calling it done. Fast sites are great. Fast sites that actually show your latest code are even better.

If you are improving front-end performance bit by bit, browser caching is one of the rare wins that is both technical and immediately visible. Set it up once, verify it properly, and let repeat visits feel a little less like starting from scratch.