CSR, SSR, SSG, ISR and streaming: choosing where pages are rendered
Client rendering vs server rendering vs static generation vs incremental regeneration, how each affects TTFB, FCP, LCP and INP, streaming SSR with Suspense, and selective hydration.
Comes up in: React, Frontend system design, Recruiter screen
Learn#
Tanya’s shop renders everything in the browser. Search engines see an empty <div id="root">, and phones show a blank screen for 3 seconds while JavaScript downloads.
Where HTML is produced changes what users wait for:
- Client-side rendering (CSR): the server sends an empty shell; JavaScript builds the page.
- Server-side rendering (SSR): the server builds the HTML for each request.
- Static site generation (SSG): HTML is built once, at deploy time.
- Incremental static regeneration (ISR): static pages rebuilt in the background after a set time.
With streaming SSR, the server sends HTML in pieces. Parts inside Suspense arrive when their data is ready:
import { createElement as h, Suspense, use } from "react";
import { renderToReadableStream } from "react-dom/server";
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
const reviews = wait(100).then(() => ["Great fit", "Fast delivery"]);
function Reviews() { return h("ul", null, use(reviews).map((r) => h("li", { key: r }, r))); }
function ProductPage() {
return h("main", null,
h("h1", null, "Cotton kurta"),
h(Suspense, { fallback: h("p", null, "Loading reviews…") }, h(Reviews)));
}
const start = Date.now();
const stream = await renderToReadableStream(h(ProductPage));
const decoder = new TextDecoder();
let n = 0;
for await (const chunk of stream) {
const text = decoder.decode(chunk);
const ms = Date.now() - start;
n++;
console.log(`chunk ${n} (${ms < 50 ? "at once" : "after the data"}):`,
text.includes("<h1>") ? "page shell with h1 and the fallback" : "",
text.includes("Great fit") ? "the reviews HTML plus a script to swap it in" : "");
}Output (verified)
chunk 1 (at once): page shell with h1 and the fallback chunk 2 (after the data): the reviews HTML plus a script to swap it in
State
- render: shell ✓, reviews: waiting
Network
empty
Page
empty
The request arrives. The server renders the product page; the reviews are wrapped in Suspense and still loading.
Read the steps as text
- The request arrives. The server renders the product page; the reviews are wrapped in Suspense and still loading.
- Chunk 1 is sent at once: the header, title, price and a "Loading reviews…" fallback. The browser can paint now.
- The reviews data arrives on the server. React renders that part and sends chunk 2: the HTML plus a tiny inline script.
- The script moves the reviews into place, replacing the fallback, even before the JavaScript bundle has loaded.
Predict#
Predict first
An SSR product page shows the price at 0.8 s, but tapping 'Add to cart' does nothing until 3 s. Why?
Server HTML is visible before it is interactive. Until hydration attaches event handlers (RCT.06.02), taps do nothing, which hurts INP and trust. Streaming and selective hydration shorten this gap; less JavaScript shortens it most.
Interview angle#
Say it like this — about 30 seconds
“CSR sends a shell and renders in the browser: simple and good for logged-in apps, but slow first paint and weak SEO. SSR renders HTML per request: fast first paint and SEO, with server cost and hydration. SSG builds pages at deploy time, served from a CDN, ideal for content. ISR rebuilds static pages periodically. Streaming SSR with Suspense sends the shell first and fills slow parts in later, and selective hydration makes the parts users touch interactive first.”
Follow-up CSR vs SSR vs SSG: which would you choose for an e-commerce product page and why?
Follow-up Explain streaming SSR with Suspense.
Follow-up What is selective hydration?
Practice#
Guided
Encode a defensible default for choosing a rendering strategy per page.
Done when
- Logged-in pages without SEO use CSR; personalized pages that need SEO use SSR.
- Rarely changing pages use SSG, hourly ones ISR, per-request ones SSR.
Remember#
Try to answer each card before you open it. Then add them to your reviews.
What is SSG?
Pages rendered to HTML at build time and served as static files.
What does streaming SSR send first?
The page shell, with Suspense fallbacks for slow parts.
Why can an SSR page look ready but ignore taps?
It has not hydrated yet, so no event handlers are attached.
What is ISR?
Static pages regenerated in the background after a set time.
Go deeper
Four layers. Stop at the one your interview needs; each ends with a quick check.
The core ideaEvery round
Check yourself: Which strategy gives the best TTFB for content pages?
SSG served from a CDN.
How it works underneathSenior rounds
renderToReadableStream (web streams) and renderToPipeableStream (Node streams) render with Suspense support. Content for a boundary arrives in a later chunk with an inline script that moves it into place Source: React: renderToReadableStream.
Check yourself: Which React API streams HTML in web-standard environments?
renderToReadableStream (react-dom/server).
Edge cases and trapsWhere people slip
Once the first chunk is sent, the status code and headers are fixed. Decide 404s and redirects before the shell, and put slow, optional parts inside Suspense.
Check yourself: Can the server change the HTTP status after streaming has started?
No. Headers are sent with the first chunk, so decide the status before the shell.
In productionStaff-level answers
Check yourself: Which part does selective hydration hydrate first?
The boundary the user is interacting with.
Finished the five steps? Mark it, and its cards join your reviews.
Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.
Interview questions this answers
- Explain streaming SSR with Suspense.
- CSR vs SSR vs SSG: which would you choose for an e-commerce product page and why?