SSR vs CSR vs ISR: Rendering Strategy Selection for SEO
On this page
For SEO, the rendering choice turns first on one question: is the page’s content in the HTML the server sends, or does it appear only after JavaScript runs in a browser? Server-side rendering (SSR), static site generation (SSG) and incremental static regeneration (ISR) put the content in the response. Client-side rendering (CSR) sends a shell and builds the page with JavaScript. Google can render JavaScript, but a page that depends on it has more ways to come back from rendering without its content. The practical default follows: use static generation or ISR for content that should rank, SSR where content must be current on every request, and CSR where search doesn’t matter.
The four modes
| Mode | Where and when the HTML is built | Content in the server response? | SEO consequence |
|---|---|---|---|
| CSR | In the browser, after JavaScript runs | No, the response is a shell | Content depends on rendering succeeding |
| SSR | On the server, for each request | Yes | Content is in the response; server work on every request |
| SSG | At build time | Yes, served as static files | Fast delivery; content fixed until the next build |
| ISR | At build time, then regenerated on a schedule or on demand | Yes | Static delivery with periodic updates |
CSR is the outlier. The server sends a near-empty page and a script bundle, and the browser assembles the content. For a user on a fast device, that can work well. For a crawler, the content exists only after the page has been rendered.
How Google handles JavaScript pages
Google’s JavaScript SEO basics describe three phases: crawling, rendering and indexing.
- Pages that return 200 are queued for rendering. Googlebot queues all pages with a 200 status code for rendering, unless a robots meta tag or header tells Google not to index the page.
- The queue has no fixed wait. A page may stay in the render queue for a few seconds, and it can take longer than that.
- Indexing uses the rendered page. Google also uses the rendered HTML to index the page.
So a CSR page isn’t indexed from its empty shell and then forgotten. It is rendered and indexed from what rendering produced. The risk lies in everything that can make that rendered page incomplete:
- Blocked resources. Google Search won’t render JavaScript from blocked files or on blocked pages. A robots.txt rule that covers the bundle or the API it calls can leave the render without its content.
- Content that waits for interaction. Google’s mobile-first indexing guidance says Google won’t load content that requires user interactions to load.
- Stale cached files. Google’s JavaScript guide says its rendering service may ignore caching headers and use outdated JavaScript or CSS. It recommends content fingerprinting in file names.
- Other crawlers. The same guide recommends server-side rendering or pre-rendering because it makes a site faster for users and crawlers, and because not all bots can run JavaScript.
SSR, SSG and ISR remove those dependencies for the content that matters, because it is already in the response.
Dynamic rendering is a workaround
Dynamic rendering serves crawlers a pre-rendered version while users get the client-rendered app. Google’s dynamic rendering documentation calls it “a workaround and not a recommended solution, because it creates additional complexities and resource requirements.” Google says Googlebot generally doesn’t consider it cloaking, as long as it produces similar content. But Google’s recommendation is clear: “we recommend that you use server-side rendering, static rendering, or hydration as a solution.” Maintaining two rendering paths is a cost the other options avoid.
Choose the mode per page type
A production site can mix page types. The useful question is which mode fits each kind of page:
- Articles, documentation, marketing pages. Content that changes on an editorial schedule: generate it statically at build time and serve it from a CDN. Rebuild when the content changes.
- Listings and content that changes daily. Use ISR. Pages are served as static files and regenerated on a schedule or on demand. The interval is an engineering choice set by how fast the data changes, not a Google rule.
- Search results and data that must be current on every request. Use SSR, and accept the server cost of rendering each request.
- Dashboards, account areas and checkout. These pages shouldn’t rank, and account and checkout pages shouldn’t be indexed at all. CSR is a simple, correct choice, and moving them to SSR buys nothing for search.
That last point can stop teams from forcing SSR everywhere. SSR on every route adds server cost, complexity and hydration work on routes where search doesn’t apply. Assigning a mode by route, based on whether the page needs to rank and how often its content changes, fits the work better than one rule for the whole site.
Frameworks: choose by capability
Meta-frameworks for React, Vue and Svelte can let you choose static generation, server rendering or client rendering per route, and several support regenerating static pages. Their API names and defaults change between versions. Choose by capability: can this framework give each route the mode it needs, and can it regenerate static pages when data changes? Then check the current documentation for how that version does it.
What rendering does to Core Web Vitals
The rendering choice is also a performance choice. Core Web Vitals targets are measured at the 75th percentile of page loads:
- Largest Contentful Paint of 2.5 seconds or less;
- Interaction to Next Paint of 200 milliseconds or less;
- Cumulative Layout Shift of 0.1 or less.
web.dev’s INP guide sets the same 200-millisecond threshold for good responsiveness.
- LCP. Static files from a CDN deliver the main content without per-request server work or a client-side build before it paints.
- INP. Server-rendered or static HTML that ships interactive JavaScript still has to hydrate in the browser. A heavy hydration step can leave the page slow to respond until it finishes. Rendering HTML on the server doesn’t remove the cost of the JavaScript that follows.
- CLS. When content is in the response from the start, the main layout is already in place when late-loading elements arrive, so there is less for them to push around.
None of this replaces a dedicated performance pass. It means the rendering decision affects speed as well as indexing.
Verify what Google sees
For any page that needs to rank, check two things:
- The raw response. View the page source, which shows what the server sent before scripts ran, not the live DOM in developer tools. If the source is a shell and the content appears only in the browser, the page depends on client-side rendering.
- Google’s rendered page. In the URL Inspection tool, run a live test and click View tested page. Google says it shows a screenshot of the rendered page, the HTML returned, the JavaScript console output and the page resources loaded.
If a page that should rank depends on client-side rendering, move it to SSG, ISR or SSR. Start with the pages that bring in revenue.
Frequently asked questions
Does CSR mean Google won’t index my content?
No. Google renders pages and uses the rendered HTML to index them. The risk is that rendering comes back without your content, because of blocked resources, content that needs a click, or stale cached scripts. For pages that need to rank, putting the content in the server response removes those risks.
Should I use SSR for everything to be safe?
No. SSR everywhere adds server cost, complexity and hydration work, with no benefit on routes that don’t need to rank. Use static generation or ISR for stable and periodically updated content, SSR for content that must be current per request, and CSR for account and checkout areas.
Is dynamic rendering still an option?
Google calls it a workaround and not a recommended solution. It generally isn’t treated as cloaking when the content is similar, but Google recommends server-side rendering, static rendering or hydration instead.
How do I check whether my content is in the initial HTML?
View the page source for the raw response, then compare it with the rendered HTML in URL Inspection’s live test.