Browser Caching Guide: Cache-Control, max-age, ETag & 304

Author Avatar Digital Bhatti
• September 27, 2026 • SEO & Performance

Browser caching reduces repeat-load requests by reusing previously downloaded responses or revalidating them instead of transferring the full resource again. Use long max-age values for safely versioned static assets, validators such as ETag or Last-Modified for changeable resources, and avoid caching private or sensitive responses in shared caches.

The goal is not to cache everything forever. The goal is to give each response an appropriate freshness policy, use validators such as ETag and Last-Modified where revalidation makes sense, and reserve long-lived caching for assets whose URLs change when their content changes.

This guide explains Cache-Control, max-age, s-maxage, no-cache, no-store, immutable, ETag, Last-Modified, conditional requests and 304 Not Modified, plus how to verify cache behavior in Chrome DevTools.

How this guide was verified

This article is based on current MDN HTTP caching, Cache-Control, ETag and 304 documentation plus current Chrome DevTools Network guidance.

It does not claim that Digital Bhatti ran a controlled repeat-load benchmark or measured universal byte, TTFB, LCP or PageSpeed improvements from any cache policy below.

Last verified: September 26, 2026.

Current HTTP caching rule

For most sites, the clean baseline is simple: fingerprinted static assets can use long freshness plus immutable; ordinary changing HTML can use no-cache with validators; personalized responses that may be cached by the browser should also be private. Reserve no-store for cases where storage itself is inappropriate.


Quick Rule

Version Static Assets Aggressively; Revalidate Changeable Content Safely

Use long-lived caching for versioned CSS, JavaScript, images and fonts whose URLs change when the content changes. Use revalidation for HTML and other responses that may change at the same URL, and reserve no-store for content that genuinely should not be stored.


1. What Is Browser Caching?

Browser caching stores eligible responses locally so they can be reused on later requests. A stored response can be fresh and reusable immediately, stale and in need of revalidation, or not storable because the server explicitly forbids storage.

Browser caching and transfer compression solve different problems. For Brotli/Gzip configuration and payload compression, use the Brotli & Gzip Compression Guide.

Do not assume that omitting Cache-Control means “not cached.” HTTP caches can apply heuristic caching when explicit freshness instructions are absent. If freshness/privacy matters, send an explicit cache policy on infrastructure you control.

2. Browser Cache vs CDN Cache vs Server Cache

Cache LayerWhere It LivesMain Purpose
Browser cacheUser deviceReuse resources between visits and navigations.
CDN/shared cacheEdge/shared infrastructureServe reusable responses closer to many users.
Page cacheServer/application layerAvoid regenerating full HTML for eligible requests.
Object cacheServer memory/application layerReuse application/database objects.

3. Fresh vs Stale Cached Responses

A response with a freshness lifetime can be reused while fresh. After that period, the response becomes stale and may need revalidation before reuse. In shared-cache responses, the Age header can show how many seconds have elapsed since the response was generated or validated by the origin.

4. Understanding Cache-Control

Cache-Control is the main HTTP header used to communicate caching behavior.

Cache-Control: public, max-age=31536000, immutable

5. What max-age Means

Cache-Control: max-age=3600

This tells the browser that the response is fresh for one hour, subject to the rest of the cache policy.

6. What s-maxage Means

s-maxage defines freshness for shared caches and is ignored by private browser caches.

Cache-Control: public, max-age=300, s-maxage=3600

7. public vs private

public allows shared-cache storage where otherwise permitted. private limits storage to a private cache such as the user's browser. For logged-in or otherwise personalized responses, explicitly marking the response private helps prevent unintended reuse by shared caches.

Cache-Control: private, no-cache

8. no-cache Does Not Mean “Do Not Cache”

no-cache allows storage but requires validation with the origin before reuse.

Cache-Control: no-cache

If the resource is unchanged, that validation can return 304 Not Modified instead of transferring the full body again. History navigation is a special case: back/forward cache or browser history behavior can restore a prior page state without the same revalidation flow.

9. no-store Means Do Not Store

Cache-Control: no-store
Do not use no-store casually

no-store prevents new cache storage but does not erase a previously stored response for the same URL. It also sacrifices useful browser features including back/forward cache. For content that simply needs to stay current, no-cache—and private when personalized—is often the more appropriate baseline.

10. no-cache vs no-store

DirectiveCan Store?Can Reuse Without Validation?
no-cacheYesNo
no-storeNoNot applicable

11. must-revalidate, immutable and Controlled Stale Reuse

must-revalidate allows normal fresh reuse but requires validation once the response becomes stale. immutable tells caches that a fresh response will not change during its freshness lifetime and fits best with versioned assets.

Cache-Control: public, max-age=31536000, immutable

stale-while-revalidate

This directive lets a cache serve a stale response for a defined window while revalidating it in the background.

Cache-Control: max-age=3600, stale-while-revalidate=86400

stale-if-error

This directive allows stale reuse for a defined window when an upstream/server error occurs, commonly for 500/502/503/504 conditions.

Cache-Control: max-age=3600, stale-if-error=86400

These directives are useful only when controlled stale reuse is acceptable for that response. They should not be added blindly to personalized, transactional or freshness-sensitive content.

12. Why Versioned Static Assets Work Well With Long Caching

/assets/app.8f3c2a.js
/assets/site.42b91f.css
/images/logo.a912fe.webp

When the asset changes, publish a new URL. The old URL can then remain cached safely for a long period.

13. HTML Usually Needs a Different Policy

HTML commonly changes at the same URL, so aggressive immutable caching is usually a poor fit. MDN's current guidance uses no-cache for ordinary non-personalized HTML so the stored representation can be revalidated instead of discarded.

Cache-Control: no-cache
ETag: "abc123"
Last-Modified: Wed, 16 Sep 2026 06:00:00 GMT
Cache Policy Rule

HTML and Fingerprinted Assets Should Not Automatically Share the Same Cache Policy

Long immutable caching fits assets whose URL changes with the content. Revalidation is often safer for HTML and other resources that change at the same URL. Add private when personalized HTML must not enter a shared cache.

14. What Is an ETag?

ETag is a server-generated validator representing a version of a resource. It can be more precise than modification timestamps because the validator need not be limited to one-second timestamp granularity.

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

15. If-None-Match and Conditional Requests

If-None-Match: "abc123"

If the current resource still has a matching ETag, the server can return 304 Not Modified. When a request contains both If-None-Match and If-Modified-Since, If-None-Match takes precedence on servers that support it.

16. Last-Modified and If-Modified-Since

Last-Modified: Wed, 16 Sep 2026 06:00:00 GMT
If-Modified-Since: Wed, 16 Sep 2026 06:00:00 GMT

If the resource has not changed since that timestamp, the server can confirm the cached copy is still valid. Last-Modified is less precise than ETag, but MDN recommends providing both validators where practical because they complement each other.

17. What 304 Not Modified Means

HTTP/1.1 304 Not Modified
ETag: "abc123"
Cache-Control: no-cache

A 304 response has no response body, so the browser can reuse its stored copy instead of downloading the entire resource again. A conforming 304 also carries cache-relevant metadata such as Cache-Control, Date, ETag, Expires and Vary where those headers would have appeared on the equivalent 200 response.

18. 200 vs 304 vs Direct Cache Reuse

OutcomeOrigin Request?Body Transferred?
Fresh browser-cache reuseOften noNo
304 Not ModifiedYes, conditionalNo full body
200 OKYesYes

19. Strong vs Weak ETags

ETag: "abc123"
ETag: W/"abc123"

A weak validator indicates semantic equivalence rather than byte-for-byte identity. For performance work, the practical priority is confirming that validation functions correctly.

20. Use Vary When the Representation Depends on Request Headers

The URL is not always the whole cache key. If the server changes the response based on a request header such as Accept-Language or Accept-Encoding, the Vary response header tells caches which request headers must match before a stored response can be reused.

Vary: Accept-Language

Use Vary narrowly. High-cardinality values such as User-Agent can fragment the cache into many variants and sharply reduce reuse. For personalized responses, prefer Cache-Control: private rather than trying to key shared caches by cookies.

21. Practical Cache Policies by Resource Type

ResourceStrategy to ConsiderCondition
Versioned CSS/JS/image/fontLong max-age + immutableURL changes when content changes.
Non-personalized HTMLno-cache + validatorsUpdates must remain current.
Personalized HTMLprivate + suitable validation/storage rulesMust not leak via shared caches.
Sensitive responseno-store where appropriateStorage itself is inappropriate.
Cacheable CDN/API response that can tolerate short stale reusestale-while-revalidate and/or stale-if-errorOnly when stale data is acceptable for the defined window.

22. Fonts and Images Still Need Their Own Delivery Strategy

Long-lived caching can be useful for versioned fonts and images, but cache policy does not replace correct font or image delivery.

Use the Web Font Performance Guide for font-specific discovery, font-display, preload and fallback behavior. Use the Image Optimization Guide for formats, dimensions, responsive images and lazy loading.

23. Third-Party Resources Limit Your Control

You cannot directly change response headers on another company's domain. If a third-party asset uses a poor caching policy, your options are to remove it, choose another provider, or self-host only where licensing and maintenance allow.

24. Browser Cache vs Full-Page Cache

A full-page cache can reduce HTML generation work on the server. Browser caching controls whether the client can reuse a response it already received.

For backend response diagnosis, use the TTFB Optimization Guide.

25. Browser Cache vs Redis or Memcached

Redis and Memcached are server-side object caches. They do not determine whether a browser reuses CSS, JavaScript, images or fonts.

Use the Redis vs Memcached Object Caching Guide for the backend layer.

26. Browser Caching vs Resource Hints

Resource hints optimize first-load discovery and priority. Browser caching optimizes reuse after a response has already been fetched and stored. They solve different stages of the loading lifecycle.

For preload, preconnect, dns-prefetch, prefetch and fetchpriority, use the Resource Hints Optimization Guide.

27. Browser Caching and Core Web Vitals

Better caching can improve repeat-visit efficiency, but it does not guarantee passing Core Web Vitals. Heavy JavaScript, layout shifts, slow uncached HTML or rendering work can remain even when static assets are cached.

Use the Core Web Vitals Optimization Guide for metric-level LCP, INP and CLS interpretation.

28. Test Browser Caching in Chrome DevTools

Open DevTools and use the Network panel. Inspect Status, Size/Transferred, request headers, response headers and Timing. Check Cache-Control, Age, ETag, Last-Modified, Vary and conditional request headers directly.

29. Use Disable Cache for First-Visit Testing

DevTools can disable the browser cache while DevTools is open. This is useful for simulating a first-time visit without cached resources affecting the result.

Do not leave cache disabled when you are trying to test repeat-load behavior.

30. Test Repeat Loads Separately

With caching enabled, reload again and look for:

  • from memory cache
  • from disk cache
  • 304 Not Modified
  • fresh 200 OK responses

The correct outcome depends on the resource's policy.

31. Normal Reload vs Hard Reload

Reload mode affects caching behavior. A normal reload can send freshness/revalidation directives while a force reload asks the browser to bypass cached responses more aggressively. Document whether you used normal reload, hard/force reload, or DevTools' Disable cache option when comparing results.

32. Blogger-Specific Browser Caching

Blogger users have limited control over Google-served HTTP response headers for Blogger-hosted pages and platform-managed assets.

Separate resources into:

  • Blogger/Google-managed resources.
  • Third-party scripts and fonts.
  • Externally hosted assets you control.

Configure cache headers only on infrastructure you actually manage. Avoid recommending Nginx or Apache snippets for Blogger-hosted HTML itself.

33. WordPress-Specific Browser Caching

WordPress sites can often control headers through the web server, CDN, managed host, or performance layer. Avoid stacking overlapping rules in Nginx, Apache, CDN and plugins without understanding which layer wins. Inspect the final response headers at the browser and, where a CDN is used, distinguish browser-cache policy from shared-cache policy such as s-maxage.

34. Common Browser-Caching Mistakes

  • Calling no-cache “no caching”: it allows storage but requires validation.
  • Using no-store everywhere: useful browser storage and bfcache opportunities can be lost.
  • Assuming no-store clears old cache entries: it prevents new storage but does not erase a previously stored response.
  • Giving HTML a one-year immutable policy: updated content can remain hidden.
  • Giving unversioned CSS/JS a long immutable policy: changed assets may not refresh promptly.
  • Omitting Cache-Control and expecting no caching: heuristic caching can still occur.
  • Using an overly broad Vary key: high-cardinality values can destroy cache reuse.
  • Testing only with cache disabled: repeat-load behavior is hidden.
  • Confusing browser cache with Redis: they are different layers.
  • Assuming third-party headers can be changed from your site: the provider controls them.

35. Browser Caching Specialist Guide Map

Observed Problem Primary Owner This Page Owns
Slow uncached HTML responseTTFB OptimizationHow the browser reuses or revalidates the response after it arrives.
Repeated backend object/database workRedis vs MemcachedClient-side cache reuse, not application object caching.
Late critical resource discoveryResource HintsRepeat-load reuse after that resource was already fetched.
Large transferred text assetsBrotli/GzipFreshness and revalidation, not compression ratio.
Fonts/images still load poorlyFont/Image guidesWhether safely versioned files can be reused efficiently.

36. Prevent Cache-Policy Regressions

Cache policies can drift when filenames stop being versioned, CDN rules change, plugins add headers, or application routes become personalized.

Track representative resource classes and verify that long-lived caching remains limited to safely versioned assets. The Web Performance Budgets & Regression Monitoring Guide covers ongoing release checks and regression control.

37. Safe Browser-Caching Optimization Workflow

  1. Inventory resource classes. HTML, CSS, JS, images, fonts and APIs.
  2. Inspect current headers. Record Cache-Control, Age, Vary and validators.
  3. Separate versioned assets from changeable URLs.
  4. Separate public/shared responses from private/personalized responses.
  5. Apply an appropriate policy per class.
  6. Test first load with cache disabled.
  7. Test normal repeat load with caching enabled.
  8. Check 304 responses where appropriate.
  9. Deploy a changed static asset and verify cache busting.
  10. Check personalized routes and CDN/shared-cache behavior separately.

38. Before-and-After Verification Checklist

  • Record URL and change date.
  • Capture response headers before changes.
  • Check Cache-Control.
  • Check Age on shared-cache responses.
  • Check Vary where content negotiation is used.
  • Check ETag.
  • Check Last-Modified.
  • Test first load with cache disabled.
  • Test normal repeat load with cache enabled.
  • Check memory/disk cache reuse.
  • Check for 304 Not Modified.
  • Verify If-None-Match/If-Modified-Since behavior where validators exist.
  • Confirm versioned assets update when their URL changes.
  • Confirm HTML updates remain visible.
  • Check personalized responses for shared-cache risks.
  • Check CDN/shared-cache headers separately where a CDN is used.

Frequently Asked Questions

What does browser caching do?

It stores eligible responses on the user's device so the browser can reuse them later or revalidate them without downloading the full body again.

Does no-cache disable caching?

No. It allows storage but requires validation with the origin before reuse.

What is the difference between no-cache and no-store?

no-cache allows storage but forces revalidation. no-store tells caches not to store the response.

What does 304 Not Modified mean?

It means a conditional request confirmed that the cached response is still valid, so the server does not retransmit the full body.

Should I use no-store for normal HTML?

Usually not merely to keep HTML fresh. Current MDN guidance generally favors no-cache so the browser can store and revalidate the page, adding private when personalized content must not be shared. Use no-store when storage itself is inappropriate.

What does Vary do?

Vary adds selected request headers to the cache key so responses generated for different values—such as languages—are not incorrectly reused for one another. Keep the key narrow to preserve cache reuse.

What is stale-while-revalidate?

It allows a cache to serve a stale response for a defined window while refreshing it in the background. Use it only when serving temporarily stale data is acceptable.

Should CSS and JavaScript be cached for one year?

Long-lived caching can be appropriate when the asset URL is versioned or fingerprinted so a content change produces a new URL.

Should HTML use immutable caching?

Usually not for ordinary changing pages. HTML commonly benefits from revalidation because the same URL may serve updated content.

Do I need both ETag and Last-Modified?

Servers can provide both. They are validators used for conditional requests and can help avoid retransmitting unchanged resources.

Does browser caching improve TTFB?

Direct cache reuse can avoid an origin request for that resource, but browser caching does not fix slow origin TTFB for uncached requests that still reach the server.

Is browser caching the same as Redis?

No. Browser caching happens on the client. Redis and Memcached are server-side object caches.

Can Blogger users control Cache-Control headers?

Control is limited for Blogger-hosted pages and Google-managed resources. You can control headers for assets served from infrastructure you manage.


Final Takeaway

Browser caching works best when the cache policy matches how a resource changes.

Use long-lived caching for versioned static assets, revalidation for content that changes at the same URL, validators such as ETag and Last-Modified to avoid unnecessary retransfers, and no-store only when storage itself is inappropriate.

The strongest strategy is to separate immutable versioned assets, changeable HTML, personalized responses and shared-cache content, then give each class a policy that balances freshness, privacy and repeat-load efficiency.

Caching Rule

Match Freshness to How the Resource Changes

Versioned static assets can usually stay fresh for a long time because a content change produces a new URL. HTML, APIs and personalized responses need more careful validation and privacy rules. Optimize reuse without hiding updates or exposing private content.

Abdul Shakoor, founder of Digital Bhatti
Written by:

Abdul Shakoor

Founder of Digital Bhatti, focused on web hosting and infrastructure, WordPress performance, Linux VPS environments, web servers and technical SEO.

This guide is documentation-led. It does not claim a Digital Bhatti cache-hit rate, byte saving, TTFB reduction, Lighthouse gain or field Core Web Vitals improvement without controlled before/after evidence.