01The Question Underneath the Acronyms

Before you pick a rendering strategy, you need to ask one honest question: when does the content change, and for whom? The four dominant approaches — Client-Side Rendering (CSR), Server-Side Rendering (SSR), Static Site Generation (SSG), and Incremental Static Regeneration (ISR) — are just different answers to that question, each making a deliberate trade between build cost, server cost, freshness, and perceived speed. None is universally correct. All are genuinely useful. The confusion usually comes from cargo-culting a strategy because a framework tutorial assumed it.

4rendering strategies in common use
60sexample ISR revalidation window
18React version that shipped streaming SSR
1×CDN hit — SSG’s runtime server cost
SSG1.0× ISR1.2× SSR1.6× CSR3.0×
Relative time to meaningful content on a cold first visit — lower is better. Illustrative, not benchmarked.

02CSR: The Browser Does the Work

Client-Side Rendering is where the modern web started in earnest. The server sends a nearly empty HTML document, the browser downloads a JavaScript bundle, executes it, fetches data, and finally paints something meaningful. The user waits through all of that sequentially.

The upside is simplicity of deployment: your app can live on a CDN as static files, your server is just an API, and the separation is clean. For highly interactive, authenticated applications — dashboards, admin tools, single-page productivity apps — CSR is still a sensible default. When you're behind a login screen, Time to First Byte barely matters; Time to Interactive is what your users feel. A well-optimised CSR app with code splitting, lazy loading, and a fast API can feel snappy.

The downside is what happens before the JavaScript executes: a blank screen, or at best a skeleton. Search engines and link-preview scrapers have historically struggled with CSR, though Google's crawler does execute JavaScript — eventually. For anything that needs to be discovered, shared, or loaded on a slow connection, CSR has real costs. It also means every user pays the hydration tax, every visit.

js
// A CSR fetch — all of this happens in the browser
useEffect(() => {
  fetch('/api/posts').then(r => r.json()).then(setPosts);
}, []);

03SSR: Fresh HTML, Server's Treat

Server-Side Rendering turns the model around. For each request, a server renders your components to HTML and sends a complete document. The browser sees real content almost immediately — critical for Time to First Contentful Paint — and then the JavaScript arrives to make it interactive, a process called hydration.

SSR shines when content is personalised, changes frequently, or must be immediately indexable. A product page that shows different pricing by region, a news feed that's different every minute, a logged-in homepage that greets you by name — these are SSR's natural territory. Frameworks like Next.js, Nuxt, and SvelteKit all treat SSR as a first-class citizen.

The cost is real, though. Every request hits a server. Under load, you're burning compute for every page view. Hydration can be surprisingly expensive on lower-end devices, because the browser must parse and execute JavaScript to attach event listeners to the server-rendered HTML. If the JS bundle is large and the device is slow, users see content they can't interact with — an uncanny valley called "zombie HTML." Streaming SSR, available in React 18 and frameworks built on it, helps by sending HTML in chunks so the browser starts rendering before the full response arrives.

Hydration is the tax you pay for interactivity — and on a slow device, it is not cheap.

js
// Next.js App Router — component fetches data on the server, no client JS needed
export default async function ProductPage({ params }) {
  const product = await fetchProduct(params.id);
  return <h1>{product.name}</h1>;
}

04SSG: Pay Once, Serve Forever

Static Site Generation moves all the rendering to build time. You run a build process — Node, a framework CLI, whatever — and it spits out a folder of HTML files that you deploy to a CDN. There is no server in the runtime sense. A request for /about returns a pre-built HTML file. It is, in terms of raw TTFB and resilience, as fast as the web gets.

SSG is the obvious choice for content that doesn't change between deployments: documentation sites, marketing pages, blogs, portfolios. Gatsby popularised the approach, Next.js codified it alongside SSR, and Astro has become the sharpest tool for pure content sites. Build times scale with content volume — a thousand-page site builds in seconds, a hundred-thousand-page catalogue might take minutes — so SSG starts to strain when the content set is large or changes without a deploy cycle.

The fundamental limitation is staleness. Once built, the content is frozen until the next deploy. If your pricing changes, if a breaking-news story updates, if inventory shifts — the static page doesn't know. For truly static content, this is a non-issue. For anything with moderate update frequency, you either trigger a redeploy on every content change (workable with a fast CI pipeline and a headless CMS webhook) or you reach for ISR.

05ISR: The Pragmatic Middle Ground

Incremental Static Regeneration is Next.js's pragmatic answer to the SSG staleness problem. You generate static pages at build time, but you attach a revalidation window to each one. When a request comes in after that window expires, the CDN serves the stale page to that visitor while simultaneously asking the server to regenerate a fresh one in the background. The next visitor gets the fresh version. Stale-while-revalidate, applied to entire pages.

The practical effect: you get most of SSG's performance (pre-built HTML, CDN delivery, low server load) while tolerating content that's "up to some minutes old" rather than "up to the last deploy." An e-commerce product page with revalidate: 60 means pricing is typically no more than about a minute stale — acceptable for most catalogues, without requiring a full rebuild on every price change.

js
// Next.js ISR — revalidate every 60 seconds
export async function generateStaticParams() { /* ... */ }

export const revalidate = 60;

export default async function ProductPage({ params }) {
  const product = await fetchProduct(params.id);
  return <h1>{product.name} — {product.price}</h1>;
}

ISR is not magic. It's still server infrastructure; the revalidation request goes somewhere. And the "stale while revalidate" model means the very first post-expiry visitor gets old data. For most use cases this is fine; for financial data or live availability, it isn't.

06The Field, at a Glance

Two of the four come up together more than any other pairing, so it helps to see them side by side — then the whole vocabulary in one place.

Head to head — SSR vs SSG
SSRSSG
Best forFresh, personalised data on every request.Fastest possible; pre-built at deploy time.
FreshnessPer request — always current.Frozen until the next deploy.
Runtime costA server renders every view.Static files on a CDN; no runtime server.
SEOExcellent — full HTML on first paint.Excellent — full HTML, pre-built.
Pick it whenDynamic or authenticated pages.Content that rarely changes.
The acronyms, decoded
TermWhat it means
CSRClient-Side Rendering — the browser fetches and renders content via JavaScript.
SSRServer-Side Rendering — the server generates full HTML on every request.
SSGStatic Site Generation — HTML built at deploy time, served from a CDN.
ISRIncremental Static Regeneration — static pages regenerated on a timed interval.
HydrationAttaching JavaScript event handlers to server-rendered HTML.
TTFBTime to First Byte — how quickly the server starts sending a response.
Stale-while-revalidateServe cached content immediately while refreshing it in the background.

How we ended up with four

  1. The SPA eraCSR takes over — ship a bundle, render everything in the browser.
  2. The SSR revivalFull HTML per request returns for speed and SEO; hydration becomes the tax.
  3. SSG goes mainstreamGatsby, then Astro, make pre-built static the default for content sites.
  4. ISR splits the differenceNext.js regenerates static pages on a timer — static speed, periodic freshness.
  5. Streaming SSR arrives (React 18)HTML streams in chunks so the browser paints before the full response lands.

Frameworks that treat these as first-class

07The Decision, Simplified

Resist the urge to pick one strategy per application and apply it everywhere. Modern frameworks let you mix at the route level: an SSG'd marketing site with one SSR'd checkout flow, or an ISR'd product catalogue with a CSR'd personalisation overlay. The question is always local: does this route's content change per-request, per-minute, per-deploy, or never?