Caching for SEO
How browser and server caching with Cache-Control, ETags, and CDNs improves performance and Core Web Vitals, and the caching pitfalls that affect crawling.
Caching stores a copy of a page or resource — in the browser, on a CDN edge, or in a crawler's own cache — so it doesn't have to be regenerated or re-downloaded. It's not a direct ranking factor, but it feeds two things that matter: page speed / Core Web Vitals (via TTFB and LCP) and crawl efficiency. Google's crawler only honors ETag and Last-Modified (plus max-age as a recrawl hint) — it prefers ETag, and 'other HTTP caching directives aren't supported.' The riskiest caching mistakes aren't slow cache durations; they're CDN misconfigurations and stale caches that block or mislead bots.
Evidence for this claim HTTP caching uses Cache-Control and validators to control reuse and revalidation. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: HTTP caching Evidence for this claim Browser caches can reuse stored responses according to HTTP caching semantics. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: HTTP cachingTL;DR — Caching means saving a copy of a page or file so it doesn’t have to be built and sent again from scratch. It makes your site faster for people and for search bots, and it lets bots skip re-downloading pages that haven’t changed. Caching won’t rank you higher on its own — but the speed it buys you, and the crawl efficiency it enables, both help indirectly.
What caching is
Every time someone opens a page, the server has to do work: build the HTML, send the images, ship the CSS and JavaScript. Caching stores a ready-made copy of those things so the next visit can reuse it instead of doing all that work again.
There are three places a copy can live that matter for SEO:
- The browser cache — files saved on the visitor’s own device, so a second page view or a return visit loads almost instantly.
- The CDN (edge) cache — copies stored on servers spread around the world, so a file is served from somewhere physically close to the user (or the bot) instead of your one origin server.
- The crawler’s own cache — Googlebot and Bingbot remember whether a page changed since last time, and skip re-downloading it if it didn’t.
Why it matters for SEO
Two reasons, and it’s worth keeping them separate:
- Speed. Faster delivery helps your Core Web Vitals — especially how quickly the server responds (TTFB) and how fast the main content shows up (LCP). Speed is part of Google’s page-experience signals.
- Crawl efficiency. When a bot can tell a page hasn’t changed, it doesn’t waste a download on it. On a big site, that frees the bot up to spend its time on new and updated pages instead.
The one thing to get straight
“Google’s cache” and “HTTP caching” are two different things. The old cache:
search operator — the “view Google’s saved copy of this page” feature — was retired
in 2024. That has nothing to do with the caching this article is about.
Cache-Control and ETag headers are alive, well, and important. A missing “cached
version” of your page in Google says nothing about whether your caching setup is
correct.
What to actually do
- Cache your static files (images, CSS, JavaScript, fonts) for a long time.
- Add versioned or hashed filenames so you can update them instantly when needed.
- Use a CDN so files load from close to your users.
- Don’t accidentally let a stale or shared cache serve the wrong thing to bots (the scary failure mode — see the Advanced and Anti-patterns tabs).
Want the header-level detail — Cache-Control directives, ETag vs. Last-Modified,
the CDN crawl-rate story, and the caching mistakes that break crawling? Switch to
the Advanced tab.
Evidence for this claim Google's crawler documentation supports ETag/If-None-Match and Last-Modified/If-Modified-Since, prefers ETag when both are present, and says other HTTP caching directives are unsupported; Google's separate max-age advice is a recrawl-timing hint, not proof it follows browser cache semantics. Scope: Google crawling Confidence: high · Verified: Crawling December: HTTP caching Evidence for this claim HTTP caching uses Cache-Control and validators to control reuse and revalidation. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: HTTP caching Evidence for this claim Browser caches can reuse stored responses according to HTTP caching semantics. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: HTTP cachingTL;DR — Caching operates on three layers that matter for SEO: browser, CDN edge, and the crawler’s own conditional-request cache. It’s not a ranking factor, but it drives page speed (TTFB/LCP, and — via bfcache — repeat-navigation Core Web Vitals) and crawl efficiency. Google’s crawler prefers ETag over Last-Modified, reads
max-ageonly as a recrawl hint, and — per its own docs — “other HTTP caching directives aren’t supported.” CDNs earn a higher crawl-rate allowance, but only once their cache is warm; the real risks are cold-cache launches and CDN/WAF misconfigurations that block bots outright.
The three layers of caching
Caching for SEO isn’t one thing — it’s three, each controlled a little differently:
- Browser cache — the visitor’s device stores files so repeat views skip the network. This is what PageSpeed Insights nags about with “Serve static assets with an efficient cache policy.”
- CDN / edge cache — a content delivery network stores copies at edge nodes worldwide (see the CDN and SEO deep dive for the full treatment). Google’s own description: CDNs are an intermediary between your origin and the user, and historically their biggest focus is caching — storing a URL’s contents so your server doesn’t have to serve that file again for a while.
- Crawler-side cache — Googlebot and Bingbot keep their own record of whether content changed, using conditional requests. This is the crawl-budget lever, and the mechanics belong to the conditional requests deep dive; here I’ll keep it at a summary level.
“Browser cache” above is shorthand for more than one mechanism. Per
MDN’s HTTP caching guide,
worth knowing apart: the private HTTP cache (per-browser, keyed by request, and
in modern browsers partitioned by top-level site to limit cross-site tracking), the
in-memory cache used for the current session, the bfcache covered below, and —
separately — a service worker’s Cache Storage, which a site’s own JavaScript
controls and which Cache-Control headers don’t govern directly. “Check the browser
cache” can mean four different debugging steps depending on which one is actually
misbehaving.
Why caching feeds Core Web Vitals
Fetching resources over the network is slow and expensive. Caching removes the network latency and the transfer cost for anything that hasn’t changed. That flows straight into two vitals-adjacent measures: TTFB (a cached response skips regeneration at the origin) and LCP (cached images/CSS/fonts render sooner).
Cache-Control, in the directives that matter
Cache-Control is the main header. The ones worth knowing:
max-age=<seconds>— how long a fresh copy is good for. For immutable, versioned assets, Chrome’s Lighthouse docs recommend caching for a year or longer — e.g.Cache-Control: max-age=31536000.no-cache— not “don’t cache.” It means “store it, but revalidate with the server before reusing it.” It still enables the lightweight 304 flow.no-store— the one that actually means don’t store any copy anywhere in an HTTP cache. It’s a caching directive, not a general privacy switch — per RFC 9111 it isn’t a reliable way to erase browser history, and it says nothing about a service worker’s own Cache Storage.public/private— whether shared caches (like a CDN) may store the response, or only the end user’s browser.immutable— skip revalidation entirely while the response is still fresh. It doesn’t mean “never goes stale” — oncemax-ageruns out, normal freshness rules apply again.must-revalidate— the opposite end of the timeline: it only matters after a response goes stale, and tells the cache it must revalidate with the origin rather than serving the stale copy anyway.s-maxage,stale-while-revalidate,stale-if-error— finer controls mostly for CDNs and other shared caches (a separate freshness lifetime for shared caches, bounded stale reuse while a background fetch runs, and bounded stale reuse on an origin error, respectively). Support varies by browser/CDN, so check current support before relying on them — and none of this extra directive set is honored by Google’s crawler, as we’ll see.
Cache-busting with versioned filenames
The trick that lets you cache aggressively and update instantly: put a content
hash in the filename — style.x234dff.css. Because the URL is the cache key,
changing the file changes the URL, so caches fetch the new version immediately while
old versions stay cached for as long as you like. Both Google’s
web.dev HTTP cache guide and
Bing’s own front-end engineering write-up
describe the same pattern — Bing hashes file contents into the URL so “the URL acts
as the cache key,” which keeps caches consistent and allows long expiration times.
The bfcache trap — where no-store quietly hurts CWV
Here’s an under-covered one. The back/forward cache (bfcache) is what makes hitting
“back” restore a page instantly. A bfcache restore skips LCP/CLS/INP measurement
entirely, so it’s pure upside for your CrUX field data. But per
Google’s bfcache guide, setting
Cache-Control: no-store on the page document itself has historically made
browsers refuse to store that page in bfcache. If you need freshness on an HTML
document but don’t want to sacrifice back/forward-cache eligibility, reach for
no-cache or max-age=0 instead of no-store.
How a cache decides “fresh enough”
Before any validator gets involved, a cache checks freshness: has the stored
response’s age passed the freshness lifetime Cache-Control gave it (or, absent an
explicit lifetime, a heuristic one the cache is allowed to guess at)? The Age
response header reports how long a shared cache has already held a response, which
is how you can tell — in DevTools or from a CDN log — how much freshness lifetime is
left. Fresh means the cache can reuse it immediately, no request at all. Stale means
it should validate before reusing it, which is exactly where ETag/If-None-Match
and Last-Modified/If-Modified-Since earn their keep — described next, for
Googlebot’s narrower version of this general HTTP mechanism.
How Googlebot uses caching (the crawl-efficiency angle)
Google made an unusually direct ask in its December 2024 Crawling December: HTTP caching post: enable caching so its crawlers can skip re-downloading unchanged pages. The striking data point in that post is that cacheable fetches have been declining — about 0.026% of total fetches were cacheable 10 years ago, and today that number is 0.017%. Small numbers, but Google clearly wants them going the other way.
ETag vs. Last-Modified — which Google prefers
Google’s crawling infrastructure supports the two standard validators: ETag
(with If-None-Match) and Last-Modified (with If-Modified-Since). Google
strongly recommends ETag
because its value is unstructured and therefore less prone to the parsing mistakes a
date string invites — and if both are present, its crawlers
use the ETag value
as the HTTP standard requires. Google still suggests setting both anyway, since
other applications such as CMSes
use them. If you do use Last-Modified, the date has to follow the HTTP format (for
example, Fri, 4 Sep 1998 19:15:56 GMT) or it won’t parse.
When the crawler’s stored validator still matches, your server returns a
304 Not Modified with no body — which is the whole point. As Google puts it, no
body means your server doesn’t spend compute
generating content
and doesn’t spend bandwidth transferring it. (That 304 machinery is the crawl-budget
mechanism covered in depth in the conditional requests article; here it’s enough to
know it exists and saves you money on both sides.)
The nuance almost everyone misses
Google’s crawler does not act on the full Cache-Control directive set the way
a browser or CDN does. Per the official crawler overview, beyond ETag/Last-Modified,
“other HTTP caching directives aren’t supported.”
The one partial exception: Google says you can optionally set max-age to
help crawlers determine when to recrawl
a URL — a recrawl hint, not a hard lock. So no-cache, s-maxage,
stale-while-revalidate, and friends still shape browser and CDN behavior, but they
don’t change how Googlebot caches. And Google’s advice on when to invalidate is
sensible: require a cache refresh
on significant changes
— updating just the copyright date in the footer isn’t significant.
CDNs and crawling
A CDN buys you more than speed. Google’s crawling infrastructure is designed to allow higher crawl rates on sites backed by a CDN, inferred from the IP address serving the URLs — it assumes a CDN-backed origin can handle more simultaneous requests.
But there’s a catch worth planning around: the cold cache. On the first access of a URL, the CDN’s cache is “cold” — nobody has requested it yet, so your origin still has to serve it at least once to warm the cache. Google warns that launching many URLs at once is therefore a real burden on crawl budget, with a high crawl rate for a few days. If you’re doing a big launch or a site migration, budget for the origin taking full load per URL before the CDN starts helping.
CDN misconfiguration is a crawling risk
The scariest caching-adjacent problems aren’t slow cache durations — they’re CDN and WAF setups that block bots. Google’s CDN post is explicit that for temporary blockages, sending 503/429 is the preferred way to signal it, whereas network timeouts are treated as terminal, “hard” errors that can get URLs removed from the index. The subtle one is a soft block: a bot-verification interstitial. The crawler only sees the challenge page, not your site — so Google strongly recommends returning a 503 to automated clients instead. The easiest way to check that a CDN isn’t quietly blocking Google is the URL Inspection tool in Search Console — look at the rendered image; if it shows a bot challenge or an empty page, talk to your CDN.
Offloading redirects to the CDN is a technique I’m a fan of. On the Marketing Speak podcast I described it as “One of my personal favorites that I don’t think it’s used enough, it’s actually just off loading your redirects to the CDN level.” (Jump to quote)
Caching pitfalls that hurt crawling and indexing
This is the angle most “caching for SEO” articles skip. A cache doesn’t just make things fast — a wrong cache can serve the wrong bytes to a bot and break crawling or indexing.
A real one: a shared cache serving a blocking robots.txt. I dug into a case of
intermittent Googlebot blocking that traced back to a shared CDN cache between a test
environment and the live site. As I wrote in
Indexed, though blocked by robots.txt:
“One possible cause would be a shared cache between a test environment and a live
environment. When the cache from the test environment is active, the robots.txt file
may include a blocking directive.” The fix was to split the cache — or exclude
.txt files from the cache in the test environment. A caching misconfiguration
directly caused a crawling failure; that’s the category of risk that actually bites.
Other pitfalls in the same family:
- Stale CDN cache serving outdated content to bots. If your edge cache holds an old version long after you’ve published a change, bots keep seeing the old one. Purge on publish, or tie cache lifetime to how often the page really changes.
Vary/ User-Agent cache fragmentation. A shared cache’s key is normally just the URL;Varyadds request headers (likeUser-AgentorAccept-Language) to that key so different variants get stored separately. Miss a header that actually changes the response and one requester can get another’s variant — the mobile/desktop or bot/human mixup. Add too many headers toVaryand you fragment the cache into so many near-duplicate keys it barely improves hit rate. Separately, modern browsers also partition their own caches by top-level site for privacy, so a resource cached while embedded on one site generally isn’t reused when embedded on another — a different mechanism fromVary, worth not conflating with it when you’re debugging a “why isn’t this cached” report.
My general rule of thumb on duration comes from the LCP work: as I put it in my Ahrefs guide to Largest Contentful Paint, “Your cache time should be as long as you are comfortable with” — and “An ideal setup is to cache for a really long period of time but purge the cache when you make a change to a page.” Long cache, instant purge. That combination is what keeps you both fast and fresh.
Is caching a ranking factor?
No — not directly. There’s no ranking signal for having ETags set or for a good
Cache-Control policy. What caching does is feed two things that matter to
visibility: page speed / Core Web Vitals (an explicit page-experience input) and
crawl efficiency (which governs how fast new and updated content gets discovered and
refreshed, indirectly touching freshness-sensitive results). Set it up because it
makes your site fast and easy to crawl — not because you expect a direct rankings
bump.
AI summary
A condensed take on the Advanced version:
- Caching = three layers for SEO: browser cache, CDN/edge cache, and the crawler’s own conditional-request cache. Each is controlled a bit differently.
- Not a ranking factor — but it drives two things that matter: page speed (TTFB/LCP, plus repeat-navigation vitals via bfcache) and crawl efficiency.
Cache-Controlbasics:max-agesets freshness (a year+ for immutable, versioned assets);no-cache= “store but revalidate” (not “don’t cache”);no-store= don’t store at all;public/privategate shared/CDN caches.- Cache-busting: put a content hash in the filename so you can cache aggressively and still update instantly (both Google and Bing use this pattern).
- bfcache trap:
Cache-Control: no-storeon the HTML document can disqualify a page from back/forward cache, silently hurting CrUX vitals. Useno-cacheormax-age=0instead. - Googlebot honors only ETag and Last-Modified (prefers ETag; reads
max-ageas a recrawl hint). Per Google, “other HTTP caching directives aren’t supported.” A matching validator returns a304 Not Modifiedwith no body, saving compute and bandwidth. - CDNs earn a higher crawl-rate allowance — but only once the cache is warm. Cold-cache launches still hit the origin once per URL; plan for it on big launches and migrations.
- Biggest risk isn’t slow caching — it’s CDN/WAF misconfig that blocks bots (return 503/429 for temporary blocks; watch for soft-block interstitials) and stale/shared caches serving the wrong content (e.g. a blocking robots.txt).
Official documentation
Primary-source documentation from the search engines and their tooling teams.
- Crawling December: HTTP caching — Gary Illyes’ Dec 2024 post: ETag vs. Last-Modified, 304 mechanics, the declining cacheable-fetches stat, and the
max-agerecrawl hint. - Google Crawler (User Agent) Overview — HTTP Caching section — the living reference: the ETag tie-break rule and the “other HTTP caching directives aren’t supported” line.
- Crawling December: CDNs and crawling — Splitt & Illyes on CDN caching, the higher crawl-rate allowance, cold-cache launches, and hard vs. soft blocks.
- Serve static assets with an efficient cache policy — the Lighthouse/PageSpeed audit and the “a year or longer” guidance for immutable assets.
- Prevent unnecessary network requests with the HTTP Cache — the directive reference and the hashed-filename cache-busting pattern.
- Back/forward cache (bfcache) — why
no-storeon the HTML document can cost you bfcache eligibility. - Crawling December series index — the full 2024 series: Googlebot, HTTP caching, faceted nav, and CDNs.
Bing / Microsoft
- Fast Front-End Performance for Microsoft Bing — Bing’s engineering team on hashing file contents into URLs for cache consistency and long expirations, and the CDN’s role in speeding static-asset delivery.
- bingbot Series: Maximizing Crawl Efficiency — the crawl-freshness logic (crawl less when content hasn’t changed) that caching supports.
- Bing Webmaster Guidelines — the hub where Bing’s CDN/performance guidance lives.
Quotes from the source
On-the-record statements from Google and from my own writing. Each link is a deep link that jumps to the quoted passage on the source page.
Google — Crawling December: HTTP caching
- “While Google’s crawling infrastructure supports heuristic caching mechanisms, in fact always had, the number of requests that can be returned from local caches has decreased: 10 years ago about 0.026% of the total fetches were cacheable, which is already not that impressive; today that number is 0.017%.” Jump to quote
- “We strongly recommend using ETag because it’s less prone to errors and mistakes (the value is not structured unlike the Last-Modified value). And, if you have the option, set them both: the internet will thank you. Maybe.” Jump to quote
- “Our recommendation is that you require a cache refresh on significant changes to your content; if you only updated the copyright date at the bottom of your page, that’s probably not significant.” Jump to quote
Google — Crawler overview (HTTP Caching section)
- “If both ETag and Last-Modified response header fields are present in the HTTP response, Google’s crawlers use the ETag value as required by the HTTP standard.” Jump to quote
- “Other HTTP caching directives aren’t supported.” Jump to quote
Google — Crawling December: CDNs and crawling
- “Historically, CDNs’ biggest focus is caching, meaning that once a user requested a URL from your site, CDNs will store the contents of that URL in their caches for a time so your server doesn’t have to serve that file again for a while.” Jump to quote
Patrick Stox — on caching and CDNs
- “Your cache time should be as long as you are comfortable with.” — me, in Ahrefs’ guide to Largest Contentful Paint. Jump to quote
- “One possible cause would be a shared cache between a test environment and a live environment. When the cache from the test environment is active, the robots.txt file may include a blocking directive.” — me, on a real crawling failure traced to a shared cache. Jump to quote
- “One of my personal favorites that I don’t think it’s used enough, it’s actually just off loading your redirects to the CDN level.” — me, on the Marketing Speak podcast. Jump to quote
Caching for SEO — cheat sheet
Cache-Control directives, decoded
| Directive | What it actually means | Use it for |
|---|---|---|
max-age=31536000 | Fresh for ~1 year | Immutable, versioned/hashed static assets |
no-cache | Store it, but revalidate before reuse (still uses 304) | HTML you want fresh but bfcache-eligible |
no-store | Don’t store any copy in an HTTP cache (not a general privacy switch) | Truly sensitive/private responses only |
public | Shared caches (CDNs) may store it | CDN-cacheable assets |
private | Only the end user’s browser may store it | Per-user responses |
immutable | Skip revalidation while still fresh (not “never stale”) | Fingerprinted assets |
must-revalidate | Once stale, must revalidate before reuse — no serving stale-on-error | Content where a wrong stale response is worse than a slower one |
s-maxage | Freshness for shared (CDN) caches specifically | Separate CDN vs. browser lifetimes |
stale-while-revalidate / stale-if-error | Bounded stale reuse while refetching / on origin error (support varies) | High-traffic pages, resilience during origin errors |
What Googlebot actually honors
- ✅
ETag+If-None-Match(Google’s preferred validator) - ✅
Last-Modified+If-Modified-Since(format the date per HTTP:Fri, 4 Sep 1998 19:15:56 GMT) - ✅
max-age— but only as a recrawl-timing hint, not a rule - ❌ Everything else — “other HTTP caching directives aren’t supported”
Fast facts
- Google prefers ETag; if both are set, ETag wins. Set both anyway (CMSes use them).
- A matching validator →
304 Not Modified, no body → saves compute and bandwidth. - Chrome/Lighthouse: cache immutable assets a year or longer.
- CDNs get a higher crawl-rate allowance — but only once the cache is warm.
- Temporary block? Return 503/429, never a silent 200-with-error or a bot interstitial.
no-storeon the HTML document can disqualify bfcache → useno-cache/max-age=0.- “Google cache” (
cache:operator) was retired in 2024 — unrelated to HTTP caching.
Caching myths and mistakes
Each one: why it’s wrong, and what to do instead.
Myth: “Caching my page will boost my rankings.” Why it’s wrong: There’s no ranking signal for caching configuration. Google’s Search Relations team has been clear caching isn’t a ranking factor. Do instead: Set up caching for the real payoffs — page speed / Core Web Vitals and crawl efficiency — both of which touch visibility indirectly. Don’t expect a direct bump.
Myth: “Google’s cache and HTTP caching are the same thing.”
Why it’s wrong: The cache: search operator and cached-page viewer were a
user-facing snapshot feature, fully retired in 2024. HTTP caching
(Cache-Control/ETag) is unrelated infrastructure.
Do instead: Ignore the missing “cached version” — it says nothing about your
caching setup. Judge your caching by headers and by crawl/performance behavior.
Myth: “no-cache means don’t cache.”
Why it’s wrong: no-cache means “store it, but revalidate with the server before
using it.” It still enables the 304 revalidation flow. no-store is the directive
that actually prevents storage.
Do instead: Use no-cache when you want freshness with revalidation; reserve
no-store for genuinely sensitive responses that must never be stored.
Myth: “A long cache duration makes Google see stale content forever.”
Why it’s wrong: Google’s crawler validates via ETag/Last-Modified on recrawl
regardless of your max-age; max-age is a recrawl hint, not a lock that stops
Google refetching.
Do instead: Cache long, but trigger a real cache-buster (new ETag/Last-Modified or
URL) on significant content changes — exactly Google’s own recommendation.
Myth: “A CDN automatically fixes crawl budget problems.” Why it’s wrong: A CDN helps only once its cache is warm; the origin still serves every URL at least once (the cold-cache problem), and a misconfigured CDN can block crawlers and make things worse. Do instead: Plan for origin load on big launches/migrations, and verify the CDN isn’t blocking bots (URL Inspection, and return 503/429 for temporary blocks).
Myth: “Any Cache-Control directive I set changes how Googlebot crawls.”
Why it’s wrong: Per Google’s docs, beyond ETag/Last-Modified (and the optional
max-age hint), “other HTTP caching directives aren’t supported” by the crawler.
Do instead: Use stale-while-revalidate, s-maxage, no-cache, etc. to tune
browser and CDN behavior — but rely on ETag/Last-Modified to influence Googlebot’s
caching.
Caching setups, before and after
1. Static asset with no cache policy → PageSpeed warning gone
- Before:
style.cssserved with noCache-Control; Lighthouse flags “Serve static assets with an efficient cache policy,” repeat visits re-download it. - After: Rename to
style.a1b2c3.cssand serveCache-Control: public, max-age=31536000, immutable. Repeat visits skip the download; a content change means a new filename, invalidating instantly.
2. HTML document you wanted “fresh” → bfcache lost
- Before:
Cache-Control: no-storeon the HTML to force freshness. Side effect: the page is disqualified from bfcache, so “back” navigations remeasure LCP/CLS/INP and drag your CrUX field data. - After: Switch to
no-cache(ormax-age=0) — you still revalidate for freshness, but the page stays bfcache-eligible and repeat navigations restore instantly.
3. Shared cache between staging and production → intermittent Googlebot block
- Before: Test and live environments share a CDN cache. When the test version is
active, the cached
robots.txtcarries a blocking directive, so Googlebot intermittently sees a disallow it shouldn’t. - After: Split the cache between environments — or exclude
.txtfiles from the test-environment cache — so liverobots.txtis never served from a staging cache. (This is a real case I wrote up in Indexed, though blocked by robots.txt.)
4. Big launch behind a CDN → crawl spike you didn’t expect
- Before: Ship 50,000 new URLs at once assuming the CDN absorbs the load. Every URL is a cold-cache miss, so the origin serves each one at least once and crawl rate stays high for days.
- After: Warm the cache ahead of the launch (or stage the rollout), and expect — and provision for — the origin taking full load per URL before the CDN starts shielding it.
HTTP caching setup checklist
- Static assets (images, CSS, JS, fonts) carry a long
max-age(a year+ for immutable/versioned files). - Versioned/hashed filenames are used so you can cache aggressively and still invalidate instantly.
-
ETagis set (Google’s preferred validator);Last-Modifiedset too, with a correctly formatted HTTP date. - Your server returns
304 Not Modified(no body) when a validator still matches. - HTML documents that need freshness use
no-cache/max-age=0, notno-store(protect bfcache eligibility). - A significant content change triggers a real cache-buster (new ETag/Last-Modified/URL), not just a footer date tweak.
- A CDN is in front of the origin, with
public/s-maxageset so shared caches may store what should be shared. - Cache is purged on publish so bots never get stale content.
- Staging and production do not share a cache for
robots.txtor other control files. - Temporary blocks return
503/429, not silent 200-with-error pages or bot interstitials. - URL Inspection in Search Console shows your real page (not a challenge or empty page) — confirming the CDN/WAF isn’t blocking Googlebot.
Updated files stay stale after deployment
Symptom: visitors keep receiving an old CSS, JavaScript, or image file. Likely cause: a long-lived cache uses the same URL for changed bytes. Fix: publish immutable assets with content-hashed filenames and update the HTML reference; purge the old edge object only when the URL itself was reused. Confirm the new URL loads.
Googlebot re-downloads unchanged pages
Symptom: logs show repeated full 200 responses for unchanged HTML. Likely
cause: missing or unstable ETag/Last-Modified validators. Fix: emit a stable,
content-correct validator and test a conditional request. A working revalidation
returns 304 when the representation has not changed.
Different users receive the wrong cached variant
Symptom: language, device, logged-in, or personalized content leaks across users.
Likely cause: the shared cache key does not include the dimension that changes the
response, or private content was marked public. Fix: correct the cache key and
Vary behavior, mark private responses appropriately, purge contaminated objects,
and retest multiple variants.
CDN cache never reports a hit
Symptom: repeat eligible requests continue reaching origin. Likely cause:
no-store/private, cookies, an overly fragmented cache key, or an edge bypass rule.
Fix: inspect response and CDN cache-status headers, change only rules safe for that
content class, then request the same cache key twice to confirm a hit.
Cache by representation risk, not by file extension alone
Classify every response before assigning policy:
- Immutable public asset: content-hashed CSS, JS, fonts, or images can use a long lifetime because changed bytes get a new URL.
- Public but changing document: HTML may be stored briefly or revalidated with
ETag/Last-Modified; freshness and fast correction matter more than maximum TTL. - User-specific response: shared caching is unsafe unless personalization is removed from the representation or correctly separated in the cache key.
- Sensitive response: use the strict policy the data requires, accepting the performance tradeoff rather than exposing content.
The useful question is not “How long can I cache this type?” It is “What would be wrong if this exact representation were reused for this requester after this change?”
Freshness, correctness, efficiency
A caching policy has to pass three tests: freshness (changes appear when promised), correctness (the right requester receives the right variant), and efficiency (unchanged bytes are not regenerated or transferred needlessly). A high hit ratio is not a success if it serves the wrong response.
Patrick's relevant free tools
- HTTP Header Checker — Inspect complete response headers across every redirect hop, with separate security and SEO grades, CDN/edge fingerprints, compression details, and a staging-versus-production diff.
- Hosting Checker — Find a domain's public IP network, CDN or edge platform, DNS and mail-host evidence, and response transfer facts without pretending a proxy reveals the origin.
- DNS Checker — Compare A, AAAA, CNAME, MX, TXT, NS, SOA, CAA, SRV, and PTR answers from Cloudflare and Google to spot DNS propagation differences.
Tools for inspecting HTTP caching
- Browser DevTools Network panel — inspect
Cache-Control,ETag,Last-Modified,Age,Vary, and whether the response came from memory, disk, or the network. curl— sendHEADand conditional requests without browser-cache ambiguity; compare the initial validator withIf-None-MatchorIf-Modified-Since.- PageSpeed Insights / Lighthouse — find static assets with inefficient cache policies; the article links the official Lighthouse cache-policy guidance.
- CDN analytics and logs — inspect hit/miss/bypass status, cache keys, origin requests, and purges at the layer that actually serves the public response.
- Server logs — verify Googlebot receives
304revalidations rather than full bodies for unchanged pages.
Prove a caching change works
Conditional-request test
Test to run: fetch the response, copy its ETag, then request it with
If-None-Match. Expected result: an unchanged representation returns 304 with
no response body. Failure interpretation: the validator is missing, unstable, or
ignored. Monitoring window: immediate. Rollback trigger: changed content is
incorrectly answered with 304 or the validator collides across variants.
Versioned-asset test
Test to run: deploy changed bytes under a new content-hashed URL and reload a page that references it. Expected result: the new URL returns the new asset while the old URL can remain cached. Failure interpretation: HTML still references the old asset or the build did not change the hash. Monitoring window: immediate after HTML/CDN propagation. Rollback trigger: broken styling or script errors on the new asset.
Shared-cache variant test
Test to run: request every meaningful variant through the CDN, repeat each, and
compare body, cache key/status, and Vary. Expected result: each requester gets
the correct representation and only safe variants are reused. Failure
interpretation: the cache key is missing a dimension or private content is shared.
Monitoring window: immediate plus production log review. Rollback trigger:
one user receives another user’s personalized or language-specific response.
Test yourself: Caching for SEO
Five quick questions on HTTP caching, CDNs, and crawling. Pick an answer for each, then check.
Caching for SEO
Caching stores a copy of a page or resource — in a browser, a CDN edge node, or a search crawler's own cache — so it can be served again without regenerating or re-downloading it. It isn't a direct ranking factor, but it feeds page speed and crawl efficiency.
Related: Core Web Vitals, TTFB, Crawl Budget
Caching for SEO
Caching is the practice of storing a copy of a page or resource so it can be reused without regenerating it on the origin server or re-transferring it over the network. On the web, HTTP caching is controlled mainly through the Cache-Control response header (and the older Expires header), plus validators — ETag and Last-Modified — that let a cache confirm content is still fresh with a lightweight 304 Not Modified response instead of a full re-download.
For SEO, caching matters in two distinct ways. First, it speeds up delivery for users and bots, which feeds into Core Web Vitals — especially TTFB and LCP — and page-experience signals. Second, it lets Googlebot and Bingbot skip re-downloading unchanged content, which conserves crawl capacity on large sites.
One important disambiguation: HTTP caching is not the same as “Google’s cache” — the cache: search operator and cached-page viewer, which Google fully retired in 2024. HTTP caching is essential, ongoing infrastructure; “Google cache” was a user-facing snapshot feature that no longer exists. Caching itself is not a direct ranking factor, but the two things it influences — page speed and crawl efficiency — both have real, if indirect, relationships to search visibility.
Related: Core Web Vitals, TTFB, Crawl Budget
Build-time retrieval analysis plus live signals for this exact article. The automatic chunk report includes a deterministic readiness score and is ready without a model download.
Search Console
sampleGA4 traffic (28d)
sampleCloudflare traffic (7d)
sampledCrUX field data (28d, phone)
sampleGoogle NLP entities
localChangelog
Updated Jul 17, 2026.
Editorial summary and recorded change details.Summary
Sharpened Cache-Control directive semantics against RFC 9111/MDN — separated distinct browser-side caching mechanisms, clarified no-store/immutable/must-revalidate scope, and added the general freshness/Age model ahead of the Googlebot-specific validator rules.
Change details
-
Split "browser cache" into its component mechanisms (private HTTP cache with top-level-site partitioning, in-memory cache, bfcache, and service worker Cache Storage) instead of treating it as one bucket.
-
Clarified that no-store is an HTTP-cache directive (not a general privacy switch) and distinguished immutable (matters while fresh) from must-revalidate (matters once stale); added must-revalidate and stale-while-revalidate/stale-if-error to the directive list and cheat-sheet table.
-
Added a general HTTP freshness/Age explanation before the Googlebot-specific ETag/Last-Modified section, and extended the Vary/cache-key pitfall with a note on browser cache partitioning by top-level site.
Full comparison unavailable — no prior snapshot was archived for this revision.
Was this helpful?
People also ask
Keep the conversation going
Ask a question here or ask other technical SEOs
My notes
- Lazy Loading
- Resource Hints
- Caching for SEO
- Back/Forward Cache (bfcache)
- HTTP/2 and HTTP/3
Glossary: Caching for SEO