Back to Performance
Performance
easy
mid

What are the differences between CSR, SSR, and streaming rendering?

CSR: server sends shell + JS; client renders. Fastest TTFB, slowest meaningful paint, weak SEO. SSR: server renders HTML per request; better LCP/SEO, higher origin cost. SSG: pre-rendered at build, served from CDN; fastest globally, but stale until rebuild. Streaming SSR: server flushes HTML in chunks as it's generated — fast FCP + good LCP. RSC: server components ship zero JS for non-interactive parts.

6 min read·~20 min to think through

Different rendering strategies trade off fast first byte vs fast meaningful paint vs interactivity vs build-time vs origin cost. The interview wants you to know the matrix.

1. Client-Side Rendering (CSR)

Server sends a near-empty HTML shell + JS bundle. Client downloads, parses, executes, fetches data, renders.

Pros:

  • Cheap origin — static hosting.
  • Rich interactivity once loaded.
  • Single bundle handles all routes.

Cons:

  • Slow FCP/LCP — nothing visible until JS loads + executes + data fetches.
  • Bad SEO — crawlers may not run JS, or rank slow pages lower.
  • Big bundle = INP regressions.

Use when: app-like internal tools, SaaS dashboards (after login), no SEO need.

2. Server-Side Rendering (SSR)

Server runs the React (or whatever) tree per request, sends HTML. Client hydrates.

Pros:

  • Fast FCP/LCP — visible content in the HTML.
  • SEO — crawlers see content.
  • One codebase server + client.

Cons:

  • Origin cost per request — server CPU + memory.
  • TTFB depends on server work — slow server = slow page.
  • Hydration is a long task — can hurt INP.

Use when: SEO matters, content varies per-user or per-request.

3. Static Site Generation (SSG)

Pages pre-rendered at build time. Served as static files from CDN.

Pros:

  • Fastest globally — CDN edge, no origin work.
  • Cheap to host — just files.
  • SEO-friendly.

Cons:

  • Stale until rebuild — must rebuild on content change.
  • Build time scales with page count — millions of pages = long builds.
  • Can't easily personalize.

Use when: marketing sites, docs, blogs, e-commerce listings that change rarely.

4. Incremental Static Regeneration (ISR)

SSG + revalidation: serve static, regenerate on a schedule or on demand.

Pros:

  • Most of SSG's speed.
  • Content can update without a full rebuild.

Cons:

  • First request after revalidation may be slower (or serve stale-while-revalidate).
  • More moving parts.

Use when: e-commerce, news sites — mostly static, occasional content updates.

5. Streaming SSR

Server starts sending HTML before the page is fully rendered. As more is computed, more is flushed.

Pros:

  • Fast FCP — header / shell paints early.
  • Slow data (a recommendations widget) doesn't block the rest.
  • React 18 renderToPipeableStream + Suspense automates this.

Cons:

  • More complex than synchronous SSR.
  • Out-of-order streaming has nuances.

Use when: SSR app with mixed-speed data dependencies.

6. React Server Components (RSC)

Components that run on the server, render to a serialized format, and ship zero JS for the non-interactive parts.

Pros:

  • Smaller client bundles — only interactive components ship JS.
  • Direct DB/server access from components.
  • Composes with streaming.

Cons:

  • New mental model — server vs client component boundaries.
  • Framework-specific (Next.js App Router today).
  • Tooling still maturing.

Use when: Next.js App Router projects; large apps with significant non-interactive content.

7. Edge rendering

SSR but at the CDN edge (Vercel Edge, Cloudflare Workers).

Pros:

  • Very low TTFB globally.
  • Personalization with edge proximity.

Cons:

  • Smaller runtime (no Node APIs).
  • Cold starts at edge functions.

Use when: globally distributed audience, dynamic but cacheable-ish.

The decision matrix

ConcernBest fit
SEO mattersSSR / SSG / RSC
Content changes constantlySSR / Streaming SSR
Content changes rarelySSG / ISR
Mixed: shell stable, data slowStreaming SSR
App-like, post-authCSR
Want minimal client JSRSC
Global audience, dynamicEdge SSR

Hybrid is the norm

Modern apps mix:

  • Static marketing pages (SSG).
  • ISR for the catalog.
  • SSR for personalized pages.
  • CSR for the dashboard (post-login).
  • Streaming + RSC for the main app shell.

Frameworks (Next.js, Remix, Astro) make hybrid easy.

Interview framing

"CSR is fast TTFB but slow meaningful paint and bad SEO — fine for post-login app shells. SSR renders per request — good for SEO and FCP/LCP, but origin cost per request. SSG pre-renders at build — fastest globally via CDN, but stale until rebuild and slow builds at scale. ISR adds revalidation on top of SSG. Streaming SSR flushes HTML in chunks as it's ready — fast FCP without making slow data block the whole page; React 18 + Suspense automates it. RSC ships zero JS for non-interactive parts, shrinking the bundle dramatically. Real apps hybridize: static marketing + ISR catalog + SSR personalized + CSR dashboard + streaming + RSC for the main shell. The decision is per-page, by which trade-offs hurt that specific page."

Follow-up questions

  • Why is streaming SSR better than synchronous SSR with Suspense?
  • What does RSC ship to the client?
  • When would you choose ISR over SSR?
  • Trade-offs of edge rendering vs origin SSR?

Common mistakes

  • CSR for SEO-critical pages.
  • SSR everywhere when most pages could be static.
  • Streaming SSR enabled but with synchronous data in the critical path.
  • Treating rendering strategy as one-size-fits-all per app.

Performance considerations

  • Each strategy optimizes a different metric. Match strategy to per-page constraints — FCP/LCP/TTFB/bundle/INP/SEO.

Edge cases

  • Authenticated content can't cache at the CDN (mostly).
  • Pages with both user-specific and shared content — split rendering.
  • Cold starts on serverless SSR.

Real-world examples

  • Next.js App Router (RSC + streaming + SSR + SSG + ISR all available).
  • Remix (SSR-first), Astro (islands + SSG), Gatsby (SSG).

Senior engineer discussion

Seniors pick rendering strategy per page based on which trade-offs hurt, hybridize freely, and don't dogmatically pick one for the whole app.

Related questions