CSR vs SSR
The single most consequential rendering decision in a frontend project is where HTML is generated: in the browser, or on the server. Get it wrong and you build performance problems into the foundation. Get it right and every optimisation after it is easier. This guide lays out exactly how client-side rendering and server-side rendering work, what each costs, and how to pick the right one, or the right mix of both.
It builds on how JavaScript renders the DOM and connects directly to the crawlability concerns in how Google crawls JavaScript and the SEO implications in SEO for single page apps.
What you'll learn
How client-side rendering works
In a client-side rendered app, the server sends an almost-empty HTML document. The browser receives it, then downloads and executes JavaScript, which fetches data and builds the entire DOM from scratch.
The CSR request sequence
<!-- What the server sends for a CSR app -->
<body>
<div id="app"></div>
<script src="/bundle.js" defer></script>
</body>
The browser paints almost nothing until the JavaScript bundle downloads, parses, and runs. The blank gap before content appears is the cost of CSR: Largest Contentful Paint is delayed by the bundle size, the network round trip for data, and the time to execute and render. After that first load, subsequent navigations are fast because the app is already running and only data moves over the network. CSR is a natural fit for authenticated dashboards and tools where the content is personal and not meant for search engines.
How server-side rendering works
In a server-side rendered app, the server generates a complete HTML document for each request, injecting data into the markup before sending it. The browser can paint meaningful content the moment it starts receiving bytes.
The SSR request sequence
// Server renders full HTML before responding (Node.js example)
app.get('/articles/:slug', async (req, res) => {
var article = await db.getArticle(req.params.slug);
res.send(renderToHTML({ article }));
});
The browser receives complete markup, parses and paints it immediately, then downloads the JavaScript bundle which hydrates the page, attaching event listeners and framework state to the server-rendered nodes. LCP is fast. The cost is server processing time per request and the hydration step on the client, which can be significant on slow devices if the bundle is large.
Performance trade-offs
Neither approach dominates the other on every metric. They trade off in complementary ways that make the choice context-dependent.
TTFB, LCP, and interactivity
SSR tends to win on Time to First Byte for simple pages because the server can stream HTML early, and it almost always wins on LCP because meaningful content arrives before JavaScript runs. CSR tends to win on repeat navigations once the app is loaded, because only JSON moves over the network and no server round trip is needed. The gap that trips up SSR apps is the time between HTML arrival and full interactivity, when the page looks ready but clicks do nothing because hydration has not finished. Minimising the JavaScript bundle and streaming HTML progressively address both sides of this trade-off.
SEO implications
Where HTML is generated affects whether and when search engines can index your content, which makes rendering strategy an SEO decision as much as a performance one.
Crawl waves and indexing delay
Googlebot can execute JavaScript, but it does so in a second crawl wave that may lag the first by seconds or days. SSR and static HTML get their content indexed in the first wave, because the markup arrives complete. A CSR page that relies entirely on JavaScript to produce content may sit in the indexing queue longer, and crawlers other than Googlebot often skip JavaScript execution entirely. For public content that must rank, SSR or static generation is the safer default. The Google crawls JavaScript guide covers the two-wave model in detail.
Hybrid approaches
The real-world answer is rarely pure CSR or pure SSR. Most production apps mix the two based on the nature of each route.
Static generation, streaming, and islands
Static site generation pre-renders pages at build time to plain HTML files, combining SSR's crawlability with a CDN's speed. Streaming SSR sends HTML in chunks as data resolves, so the browser can start rendering before the full document is ready. The islands architecture renders only the interactive components as JavaScript, leaving the rest as static HTML, which keeps the JavaScript payload small. Each of these is a point on the spectrum between CSR and SSR, and frameworks like Next.js, Nuxt, and Astro expose all of them as choices per route or per component.
Choosing a strategy
The decision follows from what a page needs to do and who needs to see it.
A decision framework
Use CSR for authenticated, personalized, or highly interactive pages where search indexing is not a goal. Use SSR for public content that must rank and where LCP matters. Use static generation for content that changes infrequently and can be built ahead of time. Use streaming or islands to get the benefits of SSR without shipping a large JavaScript runtime. In practice a single app will use all of these: the marketing pages are static, the article pages are SSR, the dashboard is CSR. Backbone.js predates these patterns, but the same principle it embodies, send the least amount of work to the client and be explicit about what updates, runs through every approach.
Frequently Asked Questions
What is client-side rendering?
Client-side rendering sends a minimal HTML shell to the browser, then JavaScript downloads and runs to fetch data and build the DOM. The browser does all the rendering work. First paint is slow until the JavaScript executes, but subsequent navigations are fast because only data moves over the network.
What is server-side rendering?
Server-side rendering generates a complete HTML document for each request. The browser receives ready-to-display markup and can paint it immediately, giving fast LCP. JavaScript then hydrates the page to make it interactive. The cost is server processing time and a hydration step on the client.
Is CSR bad for SEO?
Not necessarily. Googlebot can render JavaScript, but it processes CSR pages in a second wave that may delay indexing. SSR or static generation gets content indexed in the first crawl wave. For content that must rank quickly or for crawlers that do not execute JavaScript, SSR or static HTML is safer.
What is hydration?
Hydration is the process of attaching JavaScript event listeners and framework state to server-rendered HTML. The browser receives rendered markup and displays it immediately, then the JavaScript bundle downloads and makes it interactive. The gap between visible and interactive is a key metric to minimise.
Read next: the Rendering hub, or continue to JavaScript rendering for the DOM-level mechanics behind these strategies.
See rendering strategy in a real SPA.
The Backbone guide is built on CSR patterns and shows how to structure them cleanly.
Explore the Backbone Guide →