Engineering Journal

Most React Rendering Guides Start With the Wrong Question

A practical framework for choosing between CSR, SSR, SSG, ISR and React Server Components.

Frontend architecture should optimize for user experience, not for rendering technology. Rendering strategies are implementation choices. User experience is the design goal. This is the framework I use to derive the right one instead of picking from a list — and it's rarely the framework's default.

ReactNext.jsRenderingReact Server ComponentsArchitectureDecision Framework
Why This Exists

One question, five execution environments

As frontend architects, our first responsibility isn't choosing a framework or a rendering strategy. It's deciding where each piece of work should execute to provide the best user experience. Every rendering strategy — CSR, SSR, SSG, ISR — and every component model — Server Components, Client Components — exists to answer the same underlying question: when and where should the UI be rendered?

Older frameworks gave you one answer to that question, baked into the framework. Modern React gives you five execution environments and expects you to route each piece of work to the right one. That's strictly more power — but only if you have a framework for deciding, instead of defaulting to whichever option shipped most recently.

Two Decisions, Not One

Rendering strategy and component execution are orthogonal

1 — Rendering strategy

When is the HTML produced?

A timing decision: build time, on a schedule, or per request.

CSRSSGISRSSR
2 — Component execution

Where does each component execute?

A placement decision: on the server, or in the browser.

Server ComponentClient Component

These are independent axes, not competing philosophies. A Server Component can run inside a page produced by any of the four rendering strategies above — SSR, SSG, ISR or, with some setups, even CSR. Most of the confusion around React Server Components comes from conflating where a component executes with when the page's HTML is produced. Keep them separate and both questions get much easier to answer.

Vocabulary, for reference
CSR

The browser downloads JS and renders everything itself.

SSG

HTML is built once, ahead of time, and served identically to everyone.

ISR

Static HTML that quietly regenerates in the background on a schedule.

SSR

HTML is generated fresh, on the server, for every request.

Server Component

Runs only on the server. Its JavaScript never ships to the browser.

Client Component

Runs in the browser. Ships JavaScript and can use browser APIs.

ComponentExecutes
Server ComponentServer
Client ComponentBrowser
Rendering strategies compared as architectural trade-offs
DimensionCSRSSGISRSSR
Infra complexityLowest — static hosting, no server runtimeLowest — build once, serve staticLow-medium — needs a regeneration triggerHighest — a server renders on every request
Operational costLowestLowestLow, scales with regeneration frequencyScales directly with traffic
Initial render performanceSlowest — blank until JS loads and fetchesFastest — pre-built HTML from a CDNFast — same as SSG between regenerationsFast, but bounded by server + data-fetch latency
Interaction quality*Excellent — fully client-ownedTypically low — static content pagesTypically low-to-mediumGood, but hydration cost matters
ScalabilityTrivial — CDN serves static assetsTrivial — CDN serves static assetsHigh — most requests hit the cacheRequires scaling server compute with traffic
Developer experienceSimplest mental model, no server concernsSimple, but content goes stale between buildsMore moving parts — cache invalidation to reason aboutMost powerful, but couples rendering to server infra
Ideal use casesInternal tools, dashboards, desktop-like appsMarketing sites, docs, blogsProduct catalogs, news, e-commerceAuthenticated pages, personalization, search results

* Interaction quality is set by the component-execution decision (Server vs. Client Components), not by the rendering strategy — these are typical patterns for the content each strategy usually serves, not a rule.

The Framework

Start with the product, not the platform

Most articles on this topic start with “do you need SEO?” That question is real, but it's not first — it's a proxy for something more fundamental. The question I actually start with is what the user is doing on this screen.

Step 1 — What's the dominant UX: consumption or manipulation?

Every screen leans toward one of two modes. In a consumption experience, the user mostly reads: a marketing page, a product page, a report, a dashboard they glance at. In a manipulation experience, the user mostly acts: a spreadsheet, a whiteboard, a Kanban board, a code editor.

Consumption
Shopify product pagesGitHub README pagesNotion public docsMarketing sitesAnalytics reports
Manipulation
Jira boardsFigma canvasAG Grid tablesGmail composeMonaco editorKanban boards
Marketing pageBlog / docsProduct pageAnalytics dashboardNotion docJira boardGmailAG Grid / spreadsheetFigma / MonacoConsumptionoptimize the initial renderManipulationoptimize the interaction loop
Consumption experiences benefit most from optimizing the initial render. Manipulation experiences benefit most from optimizing the interaction loop. That single distinction will do more for your architecture than any SEO checklist.

Step 2 — Can the initial HTML be identical for every visitor?

If yes, SSG or ISR become candidates — you can produce the HTML once, or on a schedule, instead of on every request. If no — because the page depends on authentication, cookies, geolocation or personalization — you need SSR or CSR.

Step 3 — If the HTML is identical, how often does it change?

Rarely, on the order of days or a deploy → SSG. Regularly, on a schedule you can tolerate being slightly behind → ISR. Effectively on every request → SSR.

Step 4 — Which parts require continuous interaction?

This decision is made feature by feature, not page by page. An SSR page can contain a Server Component for its comments and a Client Component for its editor. Don't ask “is this page interactive?” Ask it for every component.

Client Component candidates
FormsDrag and dropMapsAnimationsKeyboard shortcutsAG GridVirtual scrolling
Server Component candidates
ReportsInvoicesCommentsProduct descriptionsBlog content
The Underrated Default

When CSR is actually the better choice

Most articles explain why SSR is useful. Very few explain when CSR is genuinely the better architecture — so let's flip the usual narrative. Applications like Gmail, Jira, Figma, AG Grid and Monaco Editor should not automatically be driven by Server Components just because RSC ships less JavaScript. What matters here isn't bundle size — it's interaction frequency: how often the user acts, and how fast the UI needs to respond to feel instant.

Marketing pageBlog / docsProduct pageAnalytics dashboardNotion docJira boardGmailAG Grid / spreadsheetFigma / MonacoConsumptionoptimize the initial renderManipulationoptimize the interaction loop
Bundle size is a proxy for user experience. For high-frequency interaction surfaces, latency per interaction is the real metric — and that number gets worse, not better, when every keystroke, drag or selection has to round-trip to a server.

Moving every interaction to the server doesn't just add latency — it adds a network dependency to something that used to be synchronous. A cell edit in a spreadsheet or a card drag on a Kanban board should never wait on a round trip to feel like it happened.

Desktop-like, CSR-first candidates
AG GridMonaco editorFigmaGoogle DocsSpreadsheetsCAD applicationsWhiteboardsOffline-first apps
Browser — client-owned appToolbarSidebarCanvas / EditorServerAuthSave / loadThe server is touched only at the edges — everything in between is one continuous client-side session.
For a manipulation-heavy product, the initial render is a rounding error in the session. Someone opens Figma once and works in it for two hours — optimizing the first 200ms of a two-hour session is optimizing the wrong number.

Offline-first and local-first applications push this further. SSR and RSC both assume a server is reachable at the moment of interaction. An application that has to keep working on a flaky connection, or fully offline, needs a client-owned architecture by construction — there is no request/response cycle to render into.

None of this makes SSR wrong. It means the decision runs through Step 1 of the framework above, not through whichever rendering strategy is fashionable this year. Server rendering can add real infrastructure and complexity without buying back any meaningful UX for a product whose entire value is a fast, continuous, local interaction loop.

Case Study

A paginated enterprise data grid

Imagine an AG Grid-style table with URL search params, pagination, virtualization, filtering, sorting, row selection and inline editing. Even though Next.js renders the surrounding page, this is fundamentally a client-driven surface — the state that matters (scroll position, selected rows, an in-progress edit) lives in the browser, changes constantly, and has nothing to do with the server.

ProductsPage — Server RenderedDataGrid — Client ComponentURL search paramsPaginationVirtualizationFilteringSortingRow selectionInline editingThe page shell is SSR. Everything inside the island stays client-side.

The page itself can be SSR — deep-linkable URLs, a fast first paint, good SEO for the shell around it. The grid itself is a Client Component — it owns its own state machine and never waits on the network to respond to a keystroke or a column resize. Nesting a Client Component inside an SSR page isn't a compromise. It's the correct architecture.

Server Components

RSC is not the future. It's a tool.

React Server Components are excellent for server-owned UI — content that doesn't change in response to the user's immediate actions. Client Components remain the best choice for interaction-heavy UI. Neither replaces the other; RSC just gives you a way to default to zero JavaScript until a component proves it needs the browser.

Many people think the biggest advantage of RSC is server-side data fetching. I disagree — the biggest advantage is shipping dramatically less JavaScript. The browser only downloads JavaScript for components that actually require browser APIs.

Bundle size
Parse time
Execution time
Hydration time
ProductPageProductInfoReviewsRelatedProductsQuantitySelectorAddToCartImageZoomServer ComponentClient Component

Only the interactive components — QuantitySelector, AddToCart and ImageZoom — are shipped to the browser.

Direct database access

Without RSCBrowser1RESTAPI2Database3
With RSCServerComponent1Database2
const product = await db.product.findUnique(...)

No REST endpoint. No JSON serialization. No client fetch.

Server-only code never reaches the browser

PrismaPostgreSQL clientsAWS SDKFile system APIs

One more clarification worth repeating: Server Components can execute during the build (SSG), during regeneration (ISR), or during every request (SSR). The rendering strategy determines when they execute. Server Components determine where they execute. RSC is not SSR.

Recap

Five steps, one goal: match the environment to the experience

Step 1

What's the dominant UX?

Consumption optimizes the initial render. Manipulation optimizes the interaction loop.

Step 2

Can everyone get the same initial HTML?

Yes → SSG or ISR become candidates. No → you need SSR or CSR.

Step 3

How often does it change?

Rarely → SSG. Regularly → ISR. Effectively every request → SSR.

Step 4

Which parts need continuous interaction?

Decided per feature, not per page — some parts of a page can be interactive while the rest isn't.

Step 5

Which environment serves each feature best?

Server Component by default. Client Component only when the interaction demands it.

What's the dominant UX?ManipulationSkip to Step 4ConsumptionSame initial HTML for everyone?NoSSRYesHow often does it change?RarelySSGRegularlyISREvery requestSSRStep 4 — decided per feature, not per pageNeeds continuous interaction?YesClient ComponentNoServer Component
Reality Check

Four things senior engineers still get wrong

Myth

SSR is always better than CSR.

Reality

SSR trades infrastructure and complexity for a faster first paint on content that differs per request — worth it for personalized or SEO-critical pages, often not worth it otherwise. CSR is frequently the right, boring answer.

Myth

RSC replaces Client Components.

Reality

RSC replaces the default of shipping JavaScript for everything. It doesn't remove the need for client-side interactivity — it just makes you opt into it deliberately, feature by feature.

Myth

Interactive applications should automatically use Server Components.

Reality

High-frequency interaction surfaces — grids, editors, canvases — get worse, not better, when their core loop depends on a server round trip. Interaction frequency should drive this decision, not a framework's default.

Myth

SEO should be the first architectural question.

Reality

SEO is one constraint among several — SSR earns its cost through faster initial rendering on personalized pages, direct server-side data access, less JavaScript shipped to the browser, response streaming and simpler data fetching, not crawlers alone. Starting with SEO skips the more common question: what is the user actually doing on this screen, and what does that interaction loop need to feel instant?

Conclusion

The goal of a frontend architect is not to maximize server rendering or client rendering. It is to place every piece of work in the execution environment that provides the best user experience, while keeping the architecture simple enough for the next engineer to reason about.

Rendering strategies and component boundaries are the vocabulary for that decision. They are not the decision itself. The decision is always about the product — Shopify, Jira, Gmail, GitHub, Figma, Notion, an internal dashboard — never about the platform.