Dynamic Serving
What dynamic serving is, the two jobs of the Vary User-Agent header, why it's a legacy pattern, and how it differs from responsive design and dynamic rendering.
Dynamic serving means one URL returns different HTML/CSS depending on the requesting user-agent — desktop gets one page, mobile gets another — and the server must send the Vary: User-Agent header so caches and crawlers don't serve the wrong version. It's one of three mobile configurations (responsive, dynamic serving, separate m-dot URLs), and Google recommends responsive design instead because dynamic serving depends on error-prone user-agent detection and correct Vary headers. Don't confuse it with dynamic rendering (pre-rendering JS for bots) — different concept, different doc. In 2026 it's mostly a legacy pattern you audit an older or enterprise site off of, not something to build fresh: mobile-first indexing raised the stakes of getting device serving wrong, and Vary: User-Agent fragments CDN caches.
Evidence for this claim Dynamic serving uses one URL with device-dependent HTML and should send Vary: User-Agent. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Mobile configurations Evidence for this claim Google supports dynamic serving but recommends responsive design because it is easier to implement and maintain. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Mobile-first indexingTL;DR — Dynamic serving is when a website uses one web address but sends a different page to phones than it does to desktops — the server looks at what device you’re on and returns different HTML. It works, but Google would rather you use responsive design (one page that just re-flows to fit the screen), because dynamic serving is easy to get wrong. If you do use it, the server has to send a special
Vary: User-Agentheader so caches don’t hand the wrong version to the wrong person.
What dynamic serving is
There are three ways a site can handle mobile visitors:
- Responsive design — one page, one set of HTML, and the layout re-flows to fit whatever screen you’re on. This is what Google recommends.
- Dynamic serving — one web address, but the server sends different HTML to phones and desktops. Same URL, different page underneath.
- Separate URLs — a whole separate mobile site on its own address, like
m.example.com.
Dynamic serving is the middle option. When your browser asks for a page, it tells the server what it is — a phone, a tablet, a desktop — in something called the user-agent. With dynamic serving, the server reads that, and decides which version of the page to send back. You and someone on a laptop can type the exact same URL and get genuinely different HTML.
The Vary: User-Agent header
Here’s the catch. Because the page changes depending on the device — but the URL
doesn’t — anything that caches pages (your browser, a CDN, your internet provider)
could accidentally save the desktop version and then hand it to the next person,
who’s on a phone. To prevent that, the server has to send a little note with every
response: Vary: User-Agent. It means “the content of this page depends on the
device, so don’t reuse a cached copy across different devices.” Forget that header
and people (and Google) can end up seeing the wrong version.
Why Google recommends against it
Dynamic serving relies on the server correctly guessing what device you’re on from the user-agent — and that guessing is genuinely hard to keep right. New devices appear, tablets get mistaken for phones, and it’s easy to ship a desktop and a mobile version that quietly drift apart. When that happens, Google can end up seeing a broken or wrong version of your page. So Google’s advice is simple: use responsive design instead, so there’s only one version and nothing to get out of sync.
The thing people get wrong
Don’t confuse dynamic serving with “dynamic rendering.” They sound almost identical and both involve the server checking the user-agent, but they solve different problems. Dynamic serving is about giving phones and desktops different HTML. Dynamic rendering is about giving search-engine bots a pre-built version of a JavaScript-heavy page. Different thing, different Google documentation — more on that in the Advanced tab.
In 2026, dynamic serving is mostly something you’ll inherit on an older or large
enterprise site, not something anyone recommends building from scratch. Want the full
version — the two jobs of the Vary header, the CDN cost most guides skip, the
cloaking question, and how to check if a site is using it — switch to the
Advanced tab.
Evidence for this claim Dynamic serving uses one URL with device-dependent HTML and should send Vary: User-Agent. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Mobile configurations Evidence for this claim Google supports dynamic serving but recommends responsive design because it is easier to implement and maintain. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Mobile-first indexingTL;DR — Dynamic serving = same URL, different HTML/CSS per user-agent, detected server-side and signaled with the
Vary: User-Agentresponse header. It’s one of three mobile configs alongside responsive design (Google’s recommendation) and separate URLs (m-dot). TheVaryheader does two jobs: (1) stops caches serving the wrong device’s version, and (2) historically helped Googlebot discover the mobile version. It has a real cost, though —Vary: User-Agentfragments CDN cache keys across every distinct UA string, multiplying origin load. User-agent detection is error-prone (stale UA lists, tablets read as phones), and a detection bug or missingVarycan make Google see the wrong or broken version — which is where the cloaking risk actually lives. Don’t confuse it with dynamic rendering (pre-rendering JS for crawlers — a different concept with its own doc). In 2026 it’s a legacy pattern to audit off of, not build fresh.
What dynamic serving is, precisely
Google’s own definition, from its mobile-first indexing best-practices doc:
“Dynamic serving: Uses the same URL regardless of device. This configuration relies
on user-agent sniffing and the Vary: user-agent HTTP response header to serve a
different version of the HTML to different devices.” The now-retired dedicated
Google page put it even more concretely — dynamic serving is “a setup where the
server responds with different HTML (and CSS) on the same URL depending on which
user agent requests the page (mobile, tablet, or desktop).”
It’s one of three mobile configurations, and the cleanest way to see it is a three-row table:
| Configuration | Same URL? | Same HTML? | Primary signal used |
|---|---|---|---|
| Responsive design | Yes | Yes | CSS media queries (nothing server-side) |
| Dynamic serving | Yes | No (by user-agent) | Vary: User-Agent header |
| Separate URLs (m-dot) | No | No | rel=canonical/rel=alternate + Vary |
Two of these three depend on the Vary header. Google is explicit that separate
URLs, “like dynamic serving, this configuration relies on the user-agent and Vary
HTTP headers.” Only responsive design has nothing to get out of sync — which is
exactly why Google recommends it (see the responsive design
deep dive, and how all three fit together in the mobile SEO hub).
How it works: user-agent detection + the Vary header
The server inspects the incoming user-agent string — the identifier every client
sends — decides whether it’s a mobile, tablet, or desktop device, and returns the
matching HTML. Because the URL is identical for everyone, the server then has to
announce that the response varies by user-agent. That’s the Vary: User-Agent
header, and Google’s archived guidance is precise that it does two distinct
jobs — don’t collapse them into one:
“It signals to caching servers used in ISPs and elsewhere that they should consider the user agent when deciding whether to serve the page from cache or not. Without the Vary HTTP header, a cache may mistakenly serve mobile users the cache of the desktop HTML page or vice versa. It helps Googlebot discover your mobile-optimized content faster, as a valid Vary HTTP header is one of the signals we may use to crawl URLs that serve mobile-optimized content.”
So job one is cache correctness — a pure UX/correctness concern independent of search engines — and job two is crawl discovery. Most competitor glossary pages only mention the first (or blur the two). In a real HTTP response it looks like this:
HTTP/1.1 200 OK
Content-Type: text/html
Vary: User-Agent
Content-Length: 5710If your server already sends a Vary header for something else (like
Accept-Encoding), you add User-Agent to the list rather than replacing it.
Worth separating clearly: Vary itself is a plain HTTP caching mechanism, not an
SEO invention. It tells a cache which request headers to fold into the cache key so
it can store the right variant — it doesn’t detect devices or understand SEO at all;
your server’s user-agent logic does that separately, and Google’s crawl-discovery
use of the header (job two, above) is Google’s own characterization of a signal it
watches for, not a caching-protocol requirement every cache follows the same way.
Send it consistently for a given URL — including on 304 Not Modified responses and
any default/fallback response — or a cache can end up holding inconsistent metadata
about what it’s storing.
The cost most guides skip: CDN cache fragmentation
Here’s the angle almost every ranking page misses. Vary: User-Agent is not free —
it fragments your cache. A cache keys entries partly on the Vary-listed headers, so
Vary: User-Agent means a separate cached copy for every distinct user-agent
string that hits the site: every browser version, every OS build, every bot. That’s
thousands of variants for content that only really has two or three real versions —
though exactly how much reuse you lose depends on your CDN’s own cache-key handling
(some normalize or group similar user-agent strings, most don’t), so there’s no
single universal hit-rate loss to quote; treat any specific multiplier, including
SiteGround’s below, as one vendor’s estimate rather than a guaranteed number for
your stack.
SiteGround put the practical cost plainly: “With the User-Agent [header] enabled, the system will keep different copies for each combination of OS and browser version visiting your site… you will have 5-30 dynamic requests for the same 100 visits. So the very same site will use 5-30 times the resources.” And this hits crawlers hard: “If such [a] bot starts crawling your site and you have the Vary: User-Agent header, each request it makes to your site would be a dynamic one and will eat up your resources.”
This isn’t new. Back in 2013, Cindy Krum warned in Search Engine Land
that enterprise CDNs treated the header as a signal that content “cannot be cached
or served from the CDN and must be fetched directly from your server” — potentially
“rendering your CDN completely useless” for dynamically-served pages. The specific
2013 vendor behavior has changed, but the underlying tension — Vary: User-Agent
fragments cache keys — is still technically real, and it’s a major reason dynamic
serving fell out of favor even among sites that weren’t worried about SEO. SiteGround
also makes the practical point that “most of the sites don’t actually serve
different HTML for their mobile versions. It’s the responsive CSS that does all the
heavy lifting” — meaning a lot of Vary: User-Agent headers in the wild are simply
leftover misconfigurations on sites that are really responsive.
Is dynamic serving cloaking?
No — not inherently. The risk is about outcome and intent, not the technique.
Detecting a device and serving it device-appropriate content is fine; the danger is
either (a) a detection bug or missing Vary header that accidentally serves Googlebot
the wrong or broken version, or (b) deliberately serving search engines meaningfully
different content than users get. Google’s own archived dynamic-serving guidance was
blunt about the trap:
“Be very careful of cloaking when detecting user agents… it should not be looking specifically for Googlebot. All Googlebot user agents identify themselves as specific mobile devices, and you should treat these Googlebot user agents exactly like you would treat these devices.”
The parallel is Google’s still-live dynamic rendering doc, which states the general principle for the related JS-rendering case: “As long as your dynamic rendering produces similar content, Googlebot won’t view dynamic rendering as cloaking,” while “serving completely different content to users and crawlers can be considered cloaking.” Same logic applies to dynamic serving: substantially-the-same content served per device is fine; a misconfiguration that looks like cloaking is the real danger.
Dynamic serving vs. dynamic rendering — don’t confuse these
This is the single clearest thing most competing content gets wrong, so it’s worth a hard line:
- Dynamic serving = device variance. Same URL, different HTML for mobile vs. desktop. The topic of this page. Google folded its guidance into the mobile-first indexing doc.
- Dynamic rendering = JS-rendering variance for bots. Serving a pre-rendered/ server-rendered version of a JavaScript-heavy page to crawlers while users get the client-rendered version. It has its own dedicated, still-live Google doc, and Bing covers it in its 2018 bingbot post (“Dynamic rendering is about detecting user agent and rendering content differently for humans and search engine crawlers” — note: that’s about JS rendering for bingbot, not device-based serving).
They’re easy to conflate because both use user-agent detection and both raise the cloaking question — but they’re different problems with different docs.
User-agent detection is genuinely error-prone
Google’s archived guidance listed the common failure modes, and they still hold: user-agent lists need constant maintenance and won’t match brand-new agents; it’s easy to mismatch — “sometimes detecting a desktop user agent as a mobile one or detecting a mobile user agent as a desktop”; and a specific classic, “a common mistake for sites is to inadvertently treat tablet devices as smartphones.” Google’s own summary — “Use the Vary HTTP header to signal your changes depending on the user agent. Detect user agent strings correctly.” — sounds simple but is the whole maintenance burden in two sentences.
Google has fielded these mistakes for a decade. Back in January 2015, Pierre Far of
Google flagged
the top implementation problems he saw — around handling JavaScript, CSS, and image
variants correctly across devices, not just the Vary header — a reminder that “add
the header” was never the whole story.
Why responsive design is now the default
Two forces made dynamic serving a legacy pattern. First, Google has recommended responsive design “because it’s the easiest design pattern to implement and maintain” since at least 2015 — one version, no device-detection risk at all. Second, mobile-first indexing completed in 2023–2024, which raised the stakes of getting device serving wrong: the mobile version is now the version Google primarily crawls, indexes, and ranks, so a dynamic-serving misconfiguration doesn’t just serve Googlebot a bad mobile page — it serves Googlebot your primary indexed content, wrong. The same push away from device-specific setups that applies to separate m-dot URLs applies to dynamic serving too: consolidate to one responsive URL and the whole class of problems disappears.
Evidence for this claim Google supports dynamic serving but recommends responsive design because it is easier to implement and maintain. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Mobile-first indexingFor the full mobile picture — content parity, Core Web Vitals on mobile, usability, interstitials, and where AMP stands — see the mobile SEO hub and the mobile SEO checklist.
How to check if a site uses dynamic serving
Concrete and fast: request the same URL twice with different user-agent strings and
compare. If the HTML differs and the response carries Vary: User-Agent, it’s
dynamic serving. If the HTML is identical (and it just re-flows via CSS), it’s
responsive. The Scripts tab has curl, DevTools, and bookmarklet versions. The tell to
watch for: HTML that differs by device but no Vary header — that’s the
misconfiguration that risks caches and crawlers seeing the wrong version.
AI summary
A condensed take on the Advanced version:
- Dynamic serving = same URL, different HTML/CSS per user-agent (desktop vs.
mobile vs. tablet), detected server-side and signaled with the
Vary: User-Agentresponse header. - One of three mobile configs: responsive design (same URL + same HTML, CSS
media queries — Google’s recommendation), dynamic serving (same URL, different
HTML), and separate URLs / m-dot (different URL + different HTML). Two of the three
depend on
Vary. - The
Vary: User-Agentheader does two jobs: (1) stops caches (browsers, CDNs, ISPs) serving a mobile visitor the cached desktop page or vice versa, and (2) historically helped Googlebot discover the mobile version. Most competitor content mentions only the first. - It has a real cost:
Vary: User-Agentfragments CDN cache keys across every distinct UA string (every browser/OS/bot), multiplying origin requests (SiteGround estimates 5–30×). A major, under-discussed reason sites moved off it. - Cloaking risk is about outcome, not the technique. Serving device-appropriate
content is fine; the danger is a detection bug/missing
Varyserving Googlebot the wrong version, or deliberately serving crawlers different content. Never special-case “Googlebot” in detection — treat its declared device like any device. - User-agent detection is error-prone: stale UA lists, desktop-as-mobile mismatches, and treating tablets as phones.
- Not the same as dynamic rendering (pre-rendering JS for bots) — different concept, different Google/Bing docs.
- Legacy pattern in 2026. Google has recommended responsive since ~2015, and mobile-first indexing (complete 2023–2024) raised the stakes of a dynamic-serving misconfiguration. Mostly something you audit an older/enterprise site off of.
- To detect it: request the same URL with a desktop vs. mobile UA, compare the
HTML, and check for the
Vary: User-Agentheader.
Official documentation
Primary-source documentation from the search engines.
- Mobile-first Indexing Best Practices — where the dynamic serving and separate-URLs definitions now live (the dedicated dynamic-serving page was folded in here) and where Google states the responsive-design recommendation.
- Dynamic Serving (original dedicated doc — archived) — the retired, much richer page (last updated Jan 2021). This is the source for the “two jobs of the Vary header” explanation and the user-agent-detection failure modes. The live URL now 301-redirects to the mobile-first indexing guide, which dropped most of this detail.
- Dynamic Rendering as a workaround — the related-but-distinct JS-rendering concept, with the “not cloaking if the content is similar” clarification. Cited here only to draw the distinction.
- Announcing mobile-first indexing for the whole web (Mar 2020) — context on why device serving matters more today.
Bing / Microsoft
- bingbot Series: JavaScript, Dynamic Rendering, and Cloaking. Oh My! (Oct 2018) — Bing’s guidance on dynamic rendering (JS-for-bots), not device-based dynamic serving. Bing does not appear to publish a dedicated device-based dynamic-serving/
Varydoc the way Google historically did; it broadly favors responsive/single-URL setups.
#:~:text= anchors. Re-confirm the snapshot loads before treating as final. Quotes from the source
On-the-record statements from Google and the industry. Live Google-doc links are deep links that jump to the quoted passage; archived and relayed sources are noted.
Google — the definition and the recommendation (live doc)
- “Dynamic serving: Uses the same URL regardless of device. This configuration relies on user-agent sniffing and the
Vary: user-agentHTTP response header to serve a different version of the HTML to different devices.” — Google Search Central docs. Jump to quote - “Separate URLs: Serves different HTML to each device, and on separate URLs. Like dynamic serving, this configuration relies on the user-agent and
VaryHTTP headers to redirect users to the device-appropriate version of the site.” Jump to quote - “Google recommends Responsive Web Design because it’s the easiest design pattern to implement and maintain.” Jump to quote
Google — the Vary header’s two jobs (archived dedicated doc, last updated Jan 2021)
- “The Vary HTTP header has two important and useful implications: It signals to caching servers used in ISPs and elsewhere that they should consider the user agent when deciding whether to serve the page from cache or not. Without the Vary HTTP header, a cache may mistakenly serve mobile users the cache of the desktop HTML page or vice versa. It helps Googlebot discover your mobile-optimized content faster.” — Google Search Central, Dynamic Serving (archived).
- “Be very careful of cloaking when detecting user agents… it should not be looking specifically for Googlebot. All Googlebot user agents identify themselves as specific mobile devices, and you should treat these Googlebot user agents exactly like you would treat these devices.” — Google Search Central, Dynamic Serving (archived).
Google — dynamic rendering (the distinct concept) (live doc)
- “As long as your dynamic rendering produces similar content, Googlebot won’t view dynamic rendering as cloaking.” Jump to quote
SiteGround — the CDN cost of Vary: User-Agent (industry)
- “With the User-Agent [header] enabled, the system will keep different copies for each combination of OS and browser version visiting your site… you will have 5-30 dynamic requests for the same 100 visits. So the very same site will use 5-30 times the resources.” — SiteGround, “How the Vary HTTP Header Can Be Bad.”
Which mobile configuration should I use?
Almost everyone should land on responsive design — but this walks the real decision, including the cases where dynamic serving or separate URLs get considered, and what to do if you’ve inherited one.
Responsive, dynamic serving, or separate URLs?
The short version: responsive is the answer for almost every case. Dynamic serving and m-dot are things you manage down on sites that already have them, not patterns to reach for new.
Dynamic serving audit checklist
- Request the same URL with representative desktop and mobile user agents and confirm whether the HTML intentionally differs.
- Send
Vary: User-Agenton every response whose representation changes by device class, including cached and error responses where applicable. - Keep primary copy, headings, internal links, images and alt text, metadata, robots directives, and structured data equivalent across versions.
- Test Googlebot Smartphone receives the same mobile representation as a normal mobile browser; never special-case the crawler.
- Check CDN cache keys and hit behavior so one device class cannot receive the other’s cached document.
- Repeat each request several times through the CDN/cache edge (not just a single origin fetch) across desktop, mobile, tablet, and bot user agents — a cache-poisoning failure only shows up once a variant is warmed and re-requested, not on the first fetch.
- Include tablets, unfamiliar user agents, and missing user-agent headers in the fallback test matrix.
- Remove
Vary: User-Agentwhen the site has become genuinely responsive and the response no longer changes. - Keep a documented migration path toward responsive design where dynamic serving is legacy rather than a requirement.
Dynamic serving — cheat sheet
Definition: same URL, different HTML/CSS per user-agent, signaled with Vary: User-Agent.
The three mobile configs
| Config | Same URL? | Same HTML? | Key signal | Google’s stance |
|---|---|---|---|---|
| Responsive design | Yes | Yes | CSS media queries | Recommended |
| Dynamic serving | Yes | No (by UA) | Vary: User-Agent | Works, fragile |
| Separate URLs (m-dot) | No | No | rel=canonical/alternate + Vary | Least recommended |
The Vary: User-Agent header — two jobs
- Cache correctness — stops browsers/CDNs/ISPs serving the wrong device’s cached version.
- Crawl discovery — historically helped Googlebot find the mobile version.
What it looks like
HTTP/1.1 200 OK
Vary: User-AgentThe hidden cost
Vary: User-Agentfragments CDN cache keys across every UA string (every browser/OS/bot).- SiteGround estimate: 5–30× the origin requests for the same traffic.
- If your HTML is actually identical per device → the header is a leftover misconfiguration; remove it.
Cloaking rule
- Serving device-appropriate content = fine.
- Detection bug / missing
Varyserving Googlebot the wrong version = the real risk. - Never special-case “Googlebot” in detection — treat its declared device like any device.
Common detection failures
- Stale user-agent string lists (miss new devices).
- Desktop read as mobile or vice versa.
- Tablets treated as smartphones (classic).
Don’t confuse with: dynamic rendering = pre-rendering JS for bots (different concept, different doc).
2026 reality: legacy pattern. Google has recommended responsive since ~2015; mobile-first indexing (complete 2023–2024) raised the stakes. Audit off it; don’t build fresh.
Detect dynamic serving on any URL
The core test: request the same URL with a desktop and a mobile user-agent,
compare the HTML, and check for the Vary: User-Agent header. If the HTML differs,
it’s dynamic serving (or m-dot, if the URL changes); if the response varies but
there’s no Vary header, that’s the misconfiguration to flag.
curl — compare desktop vs. mobile responses (macOS / Linux)
URL="https://example.com/"
DESKTOP="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0 Safari/537.36"
MOBILE="Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0 Mobile Safari/537.36"
# Fetch both, hash the body — different hashes = different HTML per device
curl -sA "$DESKTOP" "$URL" | shasum
curl -sA "$MOBILE" "$URL" | shasum
# Is the site even sending Vary: User-Agent? (headers only)
curl -sI "$URL" | grep -i '^vary:'curl — impersonate Googlebot smartphone (verify what the crawler gets)
GBOT="Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/W.X.Y.Z Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
curl -sA "$GBOT" "https://example.com/" | shasum
# Compare to the $MOBILE hash above — they should match. If Googlebot gets the
# desktop version, that's the misconfiguration that can look like cloaking.Windows (PowerShell) — same comparison
$Url = "https://example.com/"
$Desktop = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0 Safari/537.36"
$Mobile = "Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0 Mobile Safari/537.36"
(Invoke-WebRequest $Url -UserAgent $Desktop).RawContentLength
(Invoke-WebRequest $Url -UserAgent $Mobile ).RawContentLength
(Invoke-WebRequest $Url -Method Head).Headers["Vary"]Chrome DevTools — no terminal needed
- Open DevTools (
F12/Cmd+Opt+I), open the Network conditions tab (⋮→ More tools → Network conditions). - Uncheck “Use browser default,” pick a mobile UA (or paste Googlebot’s smartphone
string), and reload. Compare the rendered page and, in the Network panel, the
document request’s Response Headers for
Vary. - Toggle back to a desktop UA and reload — different HTML on the same URL is your tell.
Browser-console snippet — check the current page’s Vary header
// Paste in the DevTools Console on the page you're testing
fetch(location.href, { method: "HEAD", cache: "no-store" })
.then(r => console.log("Vary:", r.headers.get("vary") || "(none)"));Bookmarklet — one-click Vary check
javascript:(async()=>{const r=await fetch(location.href,{method:"HEAD",cache:"no-store"});alert("Vary: "+(r.headers.get("vary")||"(none set)"));})();Note: fetch only exposes response headers the server allows via CORS for
cross-origin requests, so the console/bookmarklet checks are most reliable on the
same origin you’re viewing. For a definitive header read, use curl -I or the
DevTools Network panel.
Patrick's relevant free tools
- Mobile-Friendly Tester — Run a seven-part mobile-layout diagnostic — a 0–100 product score for viewport, responsive CSS, fixed widths, font sizes, images, page weight, and plugins, plus a separate phone-viewport preview.
- Google Index Checker — Check one URL’s observable indexability blockers, or reconcile sitemap, crawl, and supplied Search Console evidence across a URL set before verifying Google’s actual state in URL Inspection.
- Canonicalization Checker — Audit HTML and HTTP canonical signals, test the canonical target, and identify observable conflicts that can cause Google to choose a different URL.
Tools for auditing device-dependent responses
curl: Repeat the same request with explicit desktop, mobile, and Googlebot Smartphone user agents; compare headers, status, body size, and content hashes.- Chrome DevTools Network panel: Override the user agent, disable cache, and inspect the actual document response rather than assuming device emulation changes it.
- Search Console URL Inspection: Check the rendered HTML Googlebot Smartphone received for representative URLs.
- A crawler with user-agent configuration: Run separate mobile and desktop crawls, then diff titles, headings, canonicals, directives, structured data, and internal links at scale.
- CDN cache analytics: Segment hits, misses, and cache keys by device class to find cache fragmentation or cross-device leakage.
Dynamic serving anti-patterns
The failure modes that turn dynamic serving from “works” into “actively hurting you”:
1. Serving different HTML with no Vary: User-Agent header.
The cardinal sin. Without it, a cache can store the desktop version and hand it to a
phone (or hand Googlebot smartphone the desktop page). The content varies but nothing
tells caches or crawlers that — so the wrong version leaks. If you serve per-device
HTML, the header is non-negotiable.
2. Adding Vary: User-Agent on a site that’s actually responsive.
The opposite mistake, and a common one. If your HTML is identical across devices,
the header does nothing useful and fragments your CDN cache across every user-agent
string (SiteGround: 5–30× the requests). Don’t add it “to be thorough” — only when
you genuinely serve different HTML per device.
3. Special-casing “Googlebot” in detection logic. Detecting the device class is fine; sniffing specifically for Googlebot and serving it something different is how accidental cloaking happens. Googlebot announces itself as a specific mobile device — treat it exactly like that device.
4. Letting desktop and mobile HTML drift out of parity. Two versions means two things to keep in sync. Under mobile-first indexing, the mobile version is what’s indexed — so content, structured data, images/alt text, and links that exist only on desktop are, for indexing purposes, gone.
5. Stale user-agent lists and tablet-as-phone mismatches. UA-detection lists rot: new devices go unmatched, desktops get read as mobile, and tablets get treated as smartphones. Detection you set up once and never revisit will quietly misclassify a growing slice of traffic.
6. Treating dynamic serving as a fresh “option” to pick. It’s not one of three co-equal choices in 2026. Google has recommended responsive since ~2015, and mobile-first indexing raised the stakes. If you’re choosing new, choose responsive; dynamic serving is legacy debt to manage down.
7. Confusing it with dynamic rendering. Reaching for JS pre-rendering docs (or Bing’s bingbot post) to configure device-based serving. Different problem, different solution — mixing them produces guidance that fits neither.
Common dynamic serving failures
Mobile users intermittently receive the desktop page
Symptom: The correct mobile response appears on a cold request but desktop HTML
appears after cache hits. Likely cause: The response varies by user agent without a
matching cache key or Vary: User-Agent. Fix: Correct the origin header and CDN
configuration, purge affected objects, then repeat cross-device requests against warm
cache entries.
Googlebot Smartphone sees less content
Symptom: URL Inspection lacks copy, links, structured data, or images available on desktop. Likely cause: Mobile templates have drifted or device detection routed Googlebot incorrectly. Fix: Restore parity from the shared content source and test the exact smartphone crawler agent alongside a normal phone agent.
A responsive site has poor cache efficiency
Symptom: HTML is identical across devices but the CDN stores many user-agent
variants. Likely cause: A legacy Vary: User-Agent header survived the migration
to responsive design. Fix: Verify the response truly no longer changes, remove the
header, purge variants, and confirm the cache consolidates.
Validate a dynamic serving change
Test representation and header agreement
Test to run: Request the same URL with desktop and mobile user agents and record
body hashes plus the Vary header. Expected result: Intentionally different bodies
both declare Vary: User-Agent; identical responsive bodies do not carry a needless
device variance. Failure interpretation: Cache signaling and origin behavior
disagree. Monitoring window: Immediate. Rollback trigger: Different bodies can
share one unvaried cache object.
Test warmed-cache isolation
Test to run: Warm the URL with one device class, then request it as the other in both orders. Expected result: Each receives its intended representation every time. Failure interpretation: The CDN cache key ignores the device variation. Monitoring window: Immediate after CDN or header changes. Rollback trigger: A mobile request receives desktop HTML or vice versa.
Test mobile content parity
Test to run: Diff a sample of desktop and mobile rendered output for primary content, metadata, directives, links, and structured data. Expected result: Layout may differ, but indexable meaning and signals remain equivalent. Failure interpretation: Template drift changes what mobile-first indexing can use. Monitoring window: On release and after recrawl in URL Inspection. Rollback trigger: The mobile representation drops an indexable element or adds a restrictive directive.
Test yourself: Dynamic Serving
Five quick questions on dynamic serving and the Vary header. Pick an answer for
each, then check.
Resources worth your time
My related writing
- The Beginner’s Guide to Technical SEO — where mobile configuration and crawl/index fit the bigger picture.
- JavaScript SEO Issues & Best Practices — relevant for the dynamic rendering concept people confuse with dynamic serving (the JS-for-bots side, not device serving).
Vary: User-Agent header — it’s a narrow, largely-legacy configuration — so the two guides above are the closest related first-party context rather than direct coverage of this exact topic.My speaking
- How Search Works (SlideShare) — my walkthrough of crawling, rendering, indexing, and ranking, including how Googlebot crawls as a smartphone (which is why device-serving misconfigurations bite under mobile-first indexing). (Standing disclaimer: “This is my understanding of systems… not going to be 100% complete or accurate.”)
From around the industry
- Mobile-first Indexing Best Practices (Google) — the current home of the dynamic serving and separate-URLs definitions and the responsive-design recommendation.
- Dynamic Serving (archived original Google doc) (Google, via Wayback Machine) — the retired, more detailed page with the two-jobs-of-Vary explanation and the user-agent-detection failure modes.
- Dynamic rendering as a workaround (Google) — the distinct JS-rendering concept, with the “similar content isn’t cloaking” clarification.
- Mobile Site Configuration & The Vary HTTP Header (Search Engine Land, Cindy Krum, 2013) — the enterprise CDN vs.
Varyheader conflict. Dated, but the underlying cache-fragmentation tension still holds. - How the Vary HTTP Header Can Be Bad (SiteGround) — the plain-terms breakdown of
Vary: User-Agentcache fragmentation and the 5–30× resource-cost estimate. - Google’s Top Three Problems They See With Dynamic Serving Mobile Sites (Search Engine Roundtable, 2015) — Pierre Far’s flagged JS/CSS/image implementation mistakes, an early “even Google was fielding this” record.
Dynamic Serving
A mobile configuration where the server returns different HTML/CSS from the same URL depending on the requesting user-agent (desktop vs. mobile), signaled with the Vary: User-Agent header.
Related: Mobile-First Indexing, Responsive Web Design
Dynamic Serving
Dynamic serving is a mobile-configuration technique where a website uses the same URL for every device, but the server inspects the requesting user-agent and returns different HTML (and CSS) depending on whether the visitor is on desktop, mobile, or tablet. Because the HTML varies by device while the URL stays fixed, the server must send the Vary: User-Agent HTTP response header on every dynamically-served response, so caches (browsers, CDNs, proxies) and search engines know the content varies by user-agent and don’t serve a cached copy of the wrong version to the wrong visitor.
It sits alongside two other mobile configurations: responsive design (same URL, same HTML/CSS everywhere, layout adapts via CSS media queries — Google’s recommended option) and separate URLs (different HTML and a different URL per device, e.g. m.example.com).
Google has consistently recommended responsive design over dynamic serving because dynamic serving depends on correct, ongoing user-agent detection and correct Vary configuration — get either wrong and Google (or a cache) can see or serve the wrong version, which can look like cloaking even when unintentional. Don’t confuse it with dynamic rendering, which is about serving a pre-rendered version of a JavaScript-heavy page to crawlers — a different concept with a different Google doc.
Related: Mobile-First Indexing, Responsive Web Design
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
Revision history
Compare the published article with an archived editorial snapshot. Added and removed words are shown only after you open a comparison.
Updated Jul 18, 2026.
Editorial summary and recorded change details.Summary
Gated the CDN cache-fragmentation cost as a vendor estimate rather than a universal number, separated Vary's protocol-level caching role from Google's own crawl-discovery signal, and added a repeated-request/cache-edge check to the audit checklist.
Change details
-
Added a caveat to the cache-fragmentation section noting the exact hit-rate loss depends on the CDN's own cache-key handling, so any specific multiplier (including SiteGround's) is one vendor's estimate, not a guaranteed number.
-
Added a paragraph distinguishing Vary as a plain HTTP caching mechanism (cache-key selection) from Google's crawl-discovery use of it, plus a note to send it consistently including on 304 responses.
-
Added an audit-checklist item to repeat requests through the CDN/cache edge across device and bot variants, since cache-poisoning failures only surface on repeated, warmed requests.