Web Performance & Standards

What is browser caching?

Browser caching is the mechanism by which a web browser stores copies of web resources, HTML pages, CSS stylesheets, JavaScript files, images, fonts, and other assets, locally on a user’s device after the first visit, so that subsequent requests for the same resources can be served from the local cache rather than fetched again from the server. When a browser has a valid cached copy of a resource it serves the cached version instantly, with zero network latency, rather than making a new HTTP request that must travel to the server and back.

Browser caching is one of the most impactful web performance optimisations available, the fastest network request is the one that is never made. A returning visitor whose browser has cached a site’s CSS, JavaScript, fonts, and images experiences dramatically faster page loads than a first-time visitor, the browser renders the page primarily from local storage rather than waiting for multiple network round trips to deliver resources.

The browser cache operates under instructions from web servers, HTTP response headers, particularly the Cache-Control header, specify how long each resource should be cached, who can cache it, and under what conditions it should be revalidated. Without cache control headers browsers apply their own heuristic caching, but explicit cache control headers enable precise control over caching behaviour that matches each resource type’s freshness requirements.

For redirect management browser caching has a specific and important implication, 301 permanent redirects are cached by browsers just like other HTTP responses. A browser that has cached a 301 redirect from URL A to URL B will go directly from URL A to URL B on subsequent visits without contacting the server, the redirect is served entirely from the local cache. This caching behaviour is a performance benefit, reducing redirect latency for returning visitors, but also a management challenge, cached 301 redirects are difficult to update or remove.

How browser caching works

Browser caching operates through a defined lifecycle, resources are stored, served from cache when valid, revalidated when expired, and eventually evicted when storage limits are reached.

Cache storage, when a browser receives an HTTP response with caching headers it stores the response body, the resource content, along with the response headers, including cache control directives, in its local cache. The cache is stored on the user’s device, in a browser-managed directory, and persists across browser sessions. A resource cached during one browsing session is available from cache in subsequent sessions until it expires or is evicted.

Cache lookup, when the browser needs to load a resource it first checks the local cache. The cache lookup uses the resource URL as the key, a cached resource is found if the exact URL matches an entry in the cache. If a matching cache entry is found the browser checks whether the entry is fresh, within its configured max-age or before its Expires date.

Serving from cache, if a fresh cache entry exists the browser serves the resource directly from local storage, no network request is made. The response arrives instantly, the time to load a cached resource is limited only by local disk or memory read speed, typically measured in microseconds.

Cache validation, conditional requests, when a cache entry exists but has expired, its max-age has elapsed, the browser does not simply discard it and fetch a fresh copy. Instead it makes a conditional request, asking the server whether the resource has changed since it was cached. If the server confirms the resource has not changed it returns a 304 Not Modified response with no body, the browser uses the cached copy and updates its expiry time. If the resource has changed the server returns a 200 OK response with the new content, the browser updates its cache with the new version.

Conditional requests use either ETag-based validation, If-None-Match request header containing the stored ETag, or date-based validation, If-Modified-Since request header containing the cached resource’s Last-Modified date. ETag validation is more reliable, it detects any content change regardless of timing.

Cache eviction, browser caches have finite storage capacity. When the cache fills up the browser evicts the least recently used entries, removing old cached resources to make space for new ones. Eviction is automatic and transparent, the browser manages its own cache capacity without user or server involvement.

Cache-Control directives for browser caching

Cache-Control headers are the primary mechanism for controlling browser caching behaviour, specifying how long resources should be cached and under what conditions they should be revalidated.

max-age, the most important browser caching directive. Specifies how many seconds from the response date the browser should consider the cached resource fresh. Cache-Control: max-age=86400 caches the resource for 86,400 seconds, 24 hours, from when it was received. During this period the browser serves the resource from cache without any network request.

no-cache, instructs the browser to store the resource in cache but always revalidate with the server before using it. The browser makes a conditional request on every use, receiving a 304 Not Modified response, and serving from cache, when the resource has not changed. No-cache is not “do not cache”, it is “always revalidate before serving”.

no-store, instructs the browser not to store the resource in cache at all. Every request fetches a fresh copy from the server. No-store is appropriate for responses containing sensitive personal data that should never persist on the user’s device.

immutable, signals that the resource will not change during its freshness period, even if the user manually reloads the page. Combined with a long max-age Cache-Control: max-age=31536000, immutable caches a versioned resource for one year without any revalidation even on manual reload. Appropriate for versioned static assets, CSS and JavaScript files with content hash filenames, that genuinely cannot change at their URL.

private, restricts caching to the browser’s private cache, shared caches like CDNs must not cache the response. Cache-Control: private, max-age=3600 allows browser caching for one hour while preventing CDN caching. Appropriate for personalised responses that should not be shared across users through CDN infrastructure.

Cached redirects, the management challenge

Permanent redirects cached in browsers create specific management challenges for redirect configuration, understanding these challenges helps design redirect infrastructure that balances performance with manageability.

How 301 redirect caching works, when a browser follows a 301 permanent redirect from URL A to URL B it caches the redirect relationship. On subsequent navigations to URL A the browser immediately navigates to URL B from its local cache, without sending any request to the server. The browser never contacts the redirect infrastructure, the redirect is transparent from a server perspective.

This caching behaviour is beneficial for performance, the redirect adds zero latency for returning visitors whose browsers have cached it. But it creates a management problem, if the redirect destination changes from URL B to URL C the browser’s cached redirect continues sending visitors to URL B rather than URL C. The change is invisible to browsers that have cached the redirect.

Duration of cached 301 redirects, without explicit Cache-Control headers 301 redirects are cached indefinitely by browsers, no expiry is applied. A browser that cached a 301 redirect years ago continues to use the cached destination unless the user manually clears their browser cache. This indefinite caching is appropriate for truly permanent redirects that will never change, but creates lasting problems for redirects whose destinations might change.

Controlling redirect cache duration, adding explicit Cache-Control headers to 301 redirect responses limits the browser caching duration, providing a maximum window during which destination changes are invisible to browsers that cached the redirect.

A redirect with Cache-Control: max-age=86400 is cached for 24 hours, destination changes propagate to all browsers within 24 hours as caches expire and browsers re-request the redirect. A redirect with Cache-Control: max-age=3600 propagates changes within one hour. A redirect with Cache-Control: no-store is never cached, every navigation to the redirect source contacts the server, but loses all redirect performance benefits for returning visitors.

302 temporary redirects and caching, 302 redirects are not cached by browsers by default, every navigation to a 302-redirected URL contacts the server for the redirect response. This non-caching behaviour ensures redirect destinations can be changed immediately without cache invalidation concerns, and ensures every redirect request registers with analytics systems for click counting. The performance benefit of caching is absent, every visit pays the redirect latency cost, but manageability is complete.

Cache busting for versioned assets

Static assets, CSS, JavaScript, fonts, images, that can be cached aggressively benefit from cache busting, a technique that ensures browsers always receive the latest version when assets change.

Content hash filenames, the standard cache busting approach for build-tool-managed assets. The asset filename includes a hash of its content, main.a3b4c5d6.js. When the file content changes its hash changes, producing a different filename, main.f7g8h9i0.js. The old filename and new filename are different URLs, the browser’s cache contains the old filename but not the new one, so the new version is fetched fresh. The old cached version remains in cache but is no longer referenced by any HTML, it is eventually evicted.

Content hash cache busting enables very aggressive browser caching, Cache-Control: max-age=31536000, immutable, one year caching with no revalidation. The URL changes with the content, so stale caches are never served.

Query string cache busting, appending a version parameter to asset URLs, main.css?v=2024011501. Changing the query string changes the URL, the browser fetches the new URL fresh. Less clean than content hash filenames but works without build tool integration, manual version number increments bust the cache.

Browser caching and SEO

Browser caching primarily affects user experience and page performance, impacting Core Web Vitals and therefore SEO rankings indirectly through performance signals.

LCP improvement through caching, Largest Contentful Paint benefits significantly from browser caching on repeat visits. CSS that controls above-the-fold layout served from cache eliminates its network fetch time. Images served from cache avoid download latency. Fonts served from cache prevent font-swap layout shifts. Repeat visits to well-cached pages load dramatically faster, achieving better LCP scores than first visits.

Core Web Vitals field data from the Chrome User Experience Report includes both first visits and return visits. Well-cached sites have better average CWV scores across all visits, improving the field data that Google uses as ranking signals.

Googlebot and browser caching, Googlebot does not maintain a persistent browser cache between crawl visits, it does not benefit from or rely on browser caching the way regular users do. Each Googlebot visit fetches resources fresh from the server. Browser caching optimisations improve performance for human users and indirectly affect Googlebot’s experience by reducing server load, allowing Googlebot to receive faster server responses.

Redirect caching and crawl efficiency, cached 301 redirects in browser caches do not affect Googlebot, Googlebot fetches the redirect source URL and receives the server’s current redirect response regardless of what browsers may have cached. Googlebot processes redirects based on the current server response, not any cached version.

Common browser caching mistakes

Not setting Cache-Control headers, relying on browser heuristic caching rather than explicit Cache-Control directives. Without explicit headers browsers apply varying default caching behaviours, typically short or no caching. Explicitly setting appropriate Cache-Control headers for each resource type ensures consistent, optimal caching behaviour.

Same caching strategy for all resources, applying the same Cache-Control header to all resources regardless of type. Static versioned assets, CSS, JavaScript with content hashes, benefit from very long cache durations, max-age=31536000, immutable. Frequently updated HTML pages benefit from short durations or no-cache. Treating all resources identically sacrifices performance for some resource types or causes stale content for others.

No cache busting for updated assets, serving long-cached static assets without a cache busting mechanism, relying on users to manually clear their browser cache to receive updated CSS or JavaScript. Without cache busting users may see broken pages when assets are updated because cached old versions are served with new HTML that references them. Content hash filenames eliminate this problem entirely.

Caching 301 redirects without considering destination changes, deploying 301 redirects with no Cache-Control header, allowing browsers to cache them indefinitely, without considering whether the redirect destination might change. If the destination later needs to change browsers that cached the original destination continue navigating to it indefinitely. Setting appropriate max-age on 301 redirects, based on the expected stability of the destination, limits the duration of stale cached redirects.

Over-caching dynamic content, setting long cache durations on dynamic content that changes frequently, causing users to see stale content after updates. User account pages, shopping cart pages, and other dynamic content should use no-cache or short max-age values, ensuring users always see current data rather than cached snapshots.

Related terms

Related terms

Ready to keep every link alive?

Ready to keep every link alive?

Ready to keep every link alive?