SSR vs CSR vs ISR: Rendering Strategy Selection for SEO
On this page
Rendering choice decides one thing that matters most for SEO: whether your content is in the HTML when Google first crawls the page. Client-side rendering (CSR) defers content behind a JavaScript render that lands in a second-wave queue, introducing delay and indexation risk. Server-side rendering (SSR), static site generation (SSG), and incremental static regeneration (ISR) all put content in the initial response, so the crawler sees it immediately. The expert default falls out of that: SSG or ISR for stable content, SSR for genuinely dynamic content, and CSR only for authenticated or otherwise no-SEO areas. The rest is choosing per page type and accepting that any real production site is a hybrid.
This post owns the rendering-strategy decision: the modes, the two-wave indexing reality, the framework mapping, and per-page-type selection. It does not diagnose why one specific page is not indexed (a separate flow), and it is not a Core Web Vitals post. Rendering touches CWV, so it appears here, but only where the rendering choice is the lever.
The four modes by where and when HTML is generated
| Mode | Where/when HTML is generated | Content in initial HTML? | SEO consequence |
|---|---|---|---|
| CSR | In the browser, after JS executes | No (initial HTML is a shell) | Content depends on the render queue; delay and indexation risk |
| SSR | On the server, per request | Yes | Content crawlable immediately; server cost per request |
| SSG | At build time, once | Yes (served as static files) | Fastest delivery from CDN; content fixed until next build |
| ISR | At build time, then regenerated on a schedule or on demand | Yes | Static speed with periodic freshness; near-static crawlability |
CSR is the outlier. The server sends a near-empty HTML shell plus a JavaScript bundle, and the browser builds the page. For a user on a fast device this is often fine. For a crawler it means the content is not in the response that gets queued first; it only appears after the page is rendered, which happens later and is not guaranteed to happen promptly. SSR, SSG, and ISR all share the property that the meaningful content is in the bytes the server returns, which is what the crawler reads first and most reliably.
Google’s two-wave model
Google processes a page in two phases. First, it crawls the raw HTML response and indexes whatever content is present there. Second, the page enters a render queue where Googlebot’s web rendering service (an evergreen Chromium) executes the JavaScript, and any content that only appears after JS runs becomes available to indexing then. The gap between the two waves is not fixed; it can be seconds, or considerably longer depending on resources and priority.
The practical consequence: content in the initial HTML is indexed in the first wave, reliably and quickly. Content that requires JavaScript to appear waits for the second wave, which is later, lower-priority for low-authority sites, and subject to the rendering service’s constraints. Those constraints matter. The renderer enforces resource and time limits, so a page that needs many heavy requests or long execution to produce content may not fully render. It does not interact with the page, so content that only appears on click, scroll, or other user action (a tab the user has to open, a section behind a “load more”) may never be seen by the crawler. Anything gated behind interaction or behind a slow, resource-heavy render is content you are betting will survive the second wave, and that bet is avoidable by putting the content in the initial HTML.
Dynamic rendering is not the answer
A tempting shortcut is dynamic rendering: detect the crawler and serve it a pre-rendered version while users get the client-rendered app. Google deprecated this as a recommendation. It is now framed as a workaround for situations with no other option, not a solution, and Google explicitly points to server-side rendering, static rendering, or hydration instead. Serving bots a different rendering path than users is also cloaking-adjacent and a maintenance burden. The durable move is to build real SSR, SSG, or ISR so that users and crawlers get the same content from the same response, rather than maintaining a separate bot-facing render.
The per-page-type decision
Production sites are hybrid by route, and the right question is not “which one mode” but “which mode for this page type.”
- Blog posts, documentation, marketing pages (stable content): SSG. The content changes rarely, so generate it once at build, serve it as static files from a CDN, and get both ideal crawlability and the fastest delivery. Rebuild when content changes.
- Frequently updated content (listings, articles with comments, content that changes daily but not per request): ISR. You get static-file speed and crawlability with periodic regeneration so the served version stays current without rebuilding the whole site. The regeneration interval is an engineering choice, not a Google rule; a value like every hour or every few minutes is an example calibrated to how fast the data actually changes, not a prescribed number.
- Search results, real-time or per-user-current data: SSR. The content genuinely differs per request and must be current, so render on the server each time. Accept the per-request server cost as the price of correctness.
- Dashboards, account areas, checkout (SEO-irrelevant): CSR. These pages should not rank and often should not be indexed at all, so the render-queue delay is a non-issue. CSR is the correct, simplest choice here, and over-engineering them into SSR is wasted effort.
The CSR-is-fine nuance is the one that stops teams from forcing SSR everywhere. SSR everywhere is expensive (server cost, complexity, hydration overhead) and unnecessary on routes where SEO does not apply. Assigning rendering by route, matching the mode to whether the page needs to rank and how its content changes, beats a single site-wide rendering dogma.
Framework mapping
Modern frameworks expose these modes per route rather than forcing one globally. The major React and Vue and Svelte meta-frameworks (Next.js, Nuxt, SvelteKit, Remix, Astro, and others) all support choosing static generation, server rendering, or client rendering on a per-route or per-component basis, and several support incremental regeneration of static pages. The specific API names and defaults shift between versions, so the durable advice is at the level of capability: pick the framework that lets you assign rendering per route, then assign SSG or ISR to your content routes and reserve CSR for the SEO-irrelevant ones. Confirm the exact current rendering options against the framework’s own documentation before relying on a specific API, because that layer changes faster than the underlying SEO principle does.
Rendering’s effect on Core Web Vitals
Rendering choice moves the Core Web Vitals, so it is worth naming the effects without turning this into a CWV post. The current thresholds, measured at the 75th percentile of field data, are LCP at or under 2.5 seconds, INP at or under 200 milliseconds (INP replaced FID in March 2024), and CLS at or under 0.1.
- LCP: SSG and ISR tend to produce the best LCP, because the content arrives as static files from a CDN edge with no per-request server work and no client-side render before the main content paints.
- INP: hydration can hurt INP. SSR and SSG that ship interactive JavaScript still have to hydrate the static HTML on the client, and a heavy hydration step makes the page slow to respond to input until it completes. Server-rendering the HTML does not automatically give you good interactivity; the JavaScript cost is still paid on the client.
- CLS: server-rendered HTML with content present from the start tends toward low CLS, because the layout is established in the initial response rather than shifting as client-rendered content pops in.
The headline is that SSG/ISR generally help LCP, hydration is the INP caveat to watch on any JS-heavy approach, and getting content into the initial response helps CLS. None of this replaces a dedicated CWV optimization pass; it just means the rendering decision is also a performance decision, not only an indexation one.
Verifying what Google actually sees
The cheapest diagnostic for any SEO-critical page is to confirm whether its content is in the initial HTML. View the page source (the raw response, not the rendered DOM in dev tools) and check whether the meaningful content is present. If the source is a near-empty shell and the content only appears in the rendered DOM, the page is relying on the second wave, and that is the signal to migrate it to SSR, SSG, or ISR by revenue priority. The migration order should follow business value: the pages that earn the most get moved off render-dependent CSR first.
Frequently Asked Questions
Is CSR a guaranteed indexing failure?
No. Google can render and index client-side content via the second wave, and well-resourced pages on authoritative sites often index fine. The problem is risk and delay, not certainty of failure. The content waits for the render queue, the renderer has resource and time limits, and interaction-dependent content may never be seen. For SEO-critical pages the safe choice is to put content in the initial HTML rather than depend on the second wave.
Should I just use SSR for everything to be safe?
No. SSR everywhere adds server cost, complexity, and a hydration step that can hurt INP, with no benefit on routes that do not need to rank. Use SSG or ISR for stable and periodically updated content, SSR where content is genuinely per-request, and CSR for authenticated or no-SEO areas. Hybrid-by-route is the expert default.
Sources
- Google Search Central, Dynamic rendering as a workaround: https://developers.google.com/search/docs/crawling-indexing/javascript/dynamic-rendering
- Google Search Central, Understand the JavaScript SEO basics: https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics
- web.dev, Core Web Vitals: https://web.dev/articles/vitals