Skip to main content
Foundations progress
beginnerPage 11 of 50

Rendering Strategies Overview

Who builds the HTML, and when? This single decision drives the entire architecture of a modern web app.

Rendering Strategies Overview

In one line: Rendering strategy answers two related questions — when is the first useful HTML produced? and how much JavaScript is needed afterward to make the page interactive? The classic answers are SSG, SSR, and CSR. Modern frameworks rarely pick just one.

In plain English

Every web page is HTML. The browser only knows how to display HTML. So somebody, somewhere, has to build that HTML — and then JavaScript usually has to come along behind it to make buttons, forms, and widgets actually work.

There are three baseline moments when the HTML can be built:

  1. Build time — on the developer's laptop or CI server, before any user shows up.
  2. Request time, on a server — when a real user asks for the page.
  3. Request time, in the user's browser — JavaScript builds the HTML after the empty shell loads.

Real apps don't pick just one. They mix static shells, cached data, streamed sections, server components, and client-side islands depending on the page. The next few pages walk through each pure choice — and the hybrids that combine them.

Rendering vs hydration — the distinction beginners miss

Two things happen on a typical modern page load, and beginners often conflate them:

StepWhat it doesWhen the user can…
RenderingProduces the HTML/DOM the user can see.…read content.
HydrationAttaches JavaScript behavior to the existing DOM.…click buttons, submit forms, see widgets update.

A page can be rendered but not yet hydrated — visible but inert. A button shows on screen; clicking it does nothing for a moment. This is the source of the famous "uncanny valley" feeling on slow modern apps.

  • SSR + hydration ships HTML first, then JS hydrates it. The page is visible early and becomes interactive later.
  • CSR delays both rendering and hydration until the JS bundle loads — slower first paint, but they happen close together.
  • SSG ships pre-built HTML; hydration is optional (Astro for example skips hydration for components that don't need it).

When someone says "server-rendered," ask: and does it also need hydration? For almost every React/Vue/Svelte app, the answer is yes.

The three pure strategies (and the hybrids on top)

Reading this diagram: The top row is the three baseline moments — every page has to be built somewhere. The dotted lines show how modern frameworks stack hybrids on top. Note that streaming SSR is framework-agnostic (Next.js, Remix, SvelteKit, Nuxt all do it), while RSCs and PPR are Next.js-specific flavors layered on top.

A first-glance comparison

StrategyWhen HTML is builtFirst useful paintJS sent to browserData freshnessServer cost per reqMain risk
SSGBuild timeVery fast (CDN hit)Optional / minimalStale until rebuild$0 (CDN only)Long build for big sites; can't personalize
SSRPer request, serverDepends on data speed — usually fast, sometimes slowHydration bundleAlways freshLinear with trafficSlow data = slow first paint
CSRIn the browserSlow (blank until JS loads)Largest (whole app)Fresh after API call$0 (CDN only)Bad SEO / LCP; bad on slow networks
ISRBuild + rebuild on TTLVery fast (CDN hit)Same as SSGStale up to TTL$0 normally; rebuild trafficEventual consistency; surprise stale data
Streaming SSRPer request, sent in chunksFast for above-the-foldHydration bundleAlways freshLinear with trafficSuspense / boundary bugs hard to debug
RSCs (React, on top of streaming SSR)Per request, server-only componentsFastLess than plain SSR (server components ship 0 JS)Always freshLinear with traffic"Server vs client" boundary is subtle
PPR (Next.js, opt-in)Static shell + per-request holesVery fast (shell is CDN)Hydration bundleMixed (static parts stale; holes fresh)Cheap (only the holes hit origin)Newer, opt-in, less ecosystem coverage

A note on "fast first paint": SSR is often described as "fast" — but it can be slow when data is slow. CSR can feel fast after the first load but typically loses on LCP. Speed isn't a single number — it's a curve that depends on data, network, and how much JS you ship.

Highlight: these are not competing options — they stack

A common misconception is that RSC, SSR, ISR, and PPR are alternatives you must choose between. They're not. On a single Next.js page you can have:

  • A statically prerendered header and footer (SSG / PPR shell).
  • A streamed server component rendering the main content (streaming SSR + RSC).
  • A cached server component that ISR-revalidates every hour.
  • A client component with "use client" running an interactive widget (CSR).

The skill is matching the right strategy to the right section of the page, not to the whole app.

A concrete real-world stack

Imagine you're building a typical SaaS app. Different pages have different needs:

PageSensible strategyWhy
Marketing homepageSSG (or PPR shell)Content rarely changes; SEO critical
Pricing / about / blogSSGSame as marketing
Product catalog listingISR or cached server renderingChanges occasionally; SEO matters; thousands of pages
Single product page (price/inventory)SSR or streamed dynamic sectionMust be live; SEO matters
Cart drawerCSR / client componentPersonalized, no SEO, needs instant updates
CheckoutSSR with client islandsPersonalized; some live validation
User dashboardSSR (behind auth) or CSRPersonalized; usually no SEO
Admin panelCSRBehind auth; SEO irrelevant; complex UI

The marketing homepage and the admin panel use completely different strategies even though they're the same app. That's normal — and good.

A quick decision tree

Use this when you have to choose for a specific page:

Common mistakes

Where people commonly trip up
  • Using CSR for public SEO pages. Google's crawler runs JS inconsistently, and most other crawlers — Slack, Discord, Twitter link previews — don't run it at all. If a human will arrive via search or a shared link, don't ship them a blank <div id="root">.
  • Treating "server-rendered" as "no JavaScript." Almost every React/Vue/Svelte SSR setup still ships a hydration bundle the same size as a SPA. If you actually need zero JS, look at Astro or HTMX — vanilla SSR is not that.
  • Treating RSC, SSR, ISR, and PPR as competing options. They stack on the same page — a static shell, a streamed server component, a cached server component, and a client island can all live in one route. The question is which mode fits each section, not the whole app.
  • Picking a strategy before picking a framework. The framework you adopt makes most of these choices for you — Next.js App Router defaults to server components with streaming, Astro defaults to SSG, Remix defaults to SSR. Choose the framework first; the strategy falls out.
  • Optimizing for a problem you don't have. PPR and selective caching are real wins at scale, but if you have 50 users a day, vanilla framework defaults will be fine for years. Don't burn complexity on traffic you don't yet see.
Highlight: this is the single most-overcomplicated topic in modern web dev

You'll see endless blog posts, conference talks, and Twitter threads arguing about rendering strategies. You don't need a strong opinion on day one. Pick what your framework defaults to:

  • Next.js (App Router) — server components by default, with streaming and selective caching.
  • Astro — SSG by default, with selective "islands" of client-side JS.
  • Remix / React Router v7 — SSR by default, with loader-based data.
  • SvelteKit — a smart mix; SSR with prerender opt-in.

Each is a reasonable default. Only optimize away from the default when you have a specific problem the default doesn't solve.

Page checkpoint

Checkpoint Quiz

Did rendering strategies stick?

Required

What's next

→ Continue to SSG — Static Site Generation for the simplest and oldest strategy: pre-build everything, serve from a CDN.