Build the mental model
CSR, SSR, and SSG are not three competing brands, they are three different answers to the same question, and comparing them side by side across a few dimensions makes the tradeoffs concrete.
Comparing these three strategies along a shared set of dimensions turns a vague preference into a concrete decision grounded in a page's actual constraints — where rendering happens, when the HTML is actually ready, how well each handles dynamic content, how cheaply each caches at a CDN edge, and how much server capacity and cost each demands at scale, compared dimension by dimension in the table below.
| Dimension | CSR / SSR / SSG |
|---|---|
| Where rendering happens | CSR: in the browser. SSR: on the server. SSG: on a build machine, ahead of time. |
| When HTML is generated | CSR: after JavaScript runs in the browser. SSR: at request time. SSG: at build time, once. |
| Dynamic content support | CSR: strong, fetches fresh data client-side. SSR: strong, fresh per request. SSG: weak without extra client-side fetching. |
| Caching at a CDN | CSR: caches the app shell only. SSR: harder, response can differ per request. SSG: excellent, whole pages are static files. |
| Server capacity needed | CSR: low, mostly serves static files. SSR: high, renders on every request. SSG: very low after the build step. |
| Typical use case | CSR: interactive apps, dashboards. SSR: personalized or frequently changing pages. SSG: docs, blogs, marketing pages. |
| SEO considerations | CSR: may need extra care for crawlers. SSR: content is visible immediately to crawlers. SSG: content is visible immediately, and stable. |
| Performance considerations | CSR: slower first paint, fast after load. SSR: fast first content, more per-request work. SSG: fastest possible delivery from a CDN. |
Once HTML reaches the browser, many applications still need JavaScript to make it interactive: clicking buttons, opening menus, submitting forms without a full reload.
The process where JavaScript attaches behavior to server-delivered HTML that is already visible is often called hydration in the frameworks that use this pattern. The browser does not have to build the page from scratch; it reuses the existing markup and wires up event handling on top of it.
Real applications rarely commit to one single rendering model across every page. A single product might serve its marketing pages as static files from a CDN, render a personalized dashboard on the server per request, and let a small interactive widget like a comment box or live chart run entirely client-side.
This mixing is called hybrid rendering, and it lets each part of an application use whichever strategy fits its own requirements rather than forcing one rule onto the whole site.
ONE APP, THREE RENDERING STRATEGIES
-----------------------------------
ONE APP, THREE RENDERING STRATEGIES
--------------------------------------
[ One Web Application ]
|
-----------------------------------------
| | |
Marketing page Dashboard page Comment widget
(SSG) (SSR) (CSR)
| | |
Built once at Server renders Loaded once, then
build time, fresh HTML per runs fully in the
served from request; JS browser; fetches
a CDN hydrates after its own dataConnect it to a real scenario
Picture a single company website built by a small team. The homepage, pricing page, and blog rarely change between visits, so they are generated once at build time and served as static files from a CDN, fast everywhere, cheap to host, easy to cache.
The logged-in customer dashboard is different: it shows account balances, order history, and settings that depend on exactly who is logged in right now, so the server renders that page fresh for each request, and JavaScript hydrates it afterward to handle clicks and form submissions.
A live chart embedded inside that dashboard updates every few seconds without reloading the surrounding page, so it is built as a small client-side rendered widget that fetches its own data independently.
None of these three decisions were made in isolation from the others, they came from asking what each individual page or component actually needed, then picking the simplest strategy that satisfied it, which is exactly why most real sites end up hybrid rather than pure CSR, pure SSR, or pure SSG.
Try the working example
function recommendRenderingStrategy({ needsSEO, needsRealtimeData, contentChangesPerUser, updateFrequency }) {
const isFrequentlyDynamic =
needsRealtimeData || updateFrequency === "seconds" || updateFrequency === "minutes";
if (contentChangesPerUser || isFrequentlyDynamic) {
return needsSEO ? "SSR" : "CSR";
}
return "SSG";
}
function recommendRenderingForSite(pages) {
return pages.map((page) => ({
page: page.name,
strategy: recommendRenderingStrategy(page),
}));
}
const site = [
{ name: "Homepage", needsSEO: true, needsRealtimeData: false, contentChangesPerUser: false, updateFrequency: "never" },
{ name: "Pricing page", needsSEO: true, needsRealtimeData: false, contentChangesPerUser: false, updateFrequency: "never" },
{ name: "Product page (live stock count)", needsSEO: true, needsRealtimeData: true, contentChangesPerUser: false, updateFrequency: "seconds" },
{ name: "Customer dashboard", needsSEO: false, needsRealtimeData: true, contentChangesPerUser: true, updateFrequency: "seconds" },
{ name: "Live chart widget", needsSEO: false, needsRealtimeData: true, contentChangesPerUser: true, updateFrequency: "seconds" },
];
const plan = recommendRenderingForSite(site);
plan.forEach((entry) => console.log(`${entry.page}: ${entry.strategy}`));
const uniqueStrategies = new Set(plan.map((entry) => entry.strategy));
console.log(`\nDistinct strategies used across this one site: ${uniqueStrategies.size}`);
console.log(`(${[...uniqueStrategies].join(", ")}) -- this is a hybrid site.`);The site plan prints one recommendation per page — Homepage: SSG, Pricing page: SSG, Product page (live stock count): SSR, Customer dashboard: CSR, Live chart widget: CSR — then reports 3 distinct strategies used, confirming the site is hybrid.5-minute try-it
Take a real website you use (a bank, a shop, a news site) and try to guess which pages are likely SSG, SSR, or CSR based on how they behave — fast and unchanging vs. personalized vs. highly interactive.
One important caution
Assuming a whole site must pick exactly one rendering strategy — most real sites mix strategies page by page.
Confusing hydration with the initial render — hydration only attaches behavior to HTML that already exists in the browser.
MDN — Hydration (Glossary) — How the Web Works