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.
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.
Rendering strategy and component execution are orthogonal
When is the HTML produced?
A timing decision: build time, on a schedule, or per request.
Where does each component execute?
A placement decision: on the server, or in the browser.
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.
The browser downloads JS and renders everything itself.
HTML is built once, ahead of time, and served identically to everyone.
Static HTML that quietly regenerates in the background on a schedule.
HTML is generated fresh, on the server, for every request.
Runs only on the server. Its JavaScript never ships to the browser.
Runs in the browser. Ships JavaScript and can use browser APIs.
| Component | Executes |
|---|---|
| Server Component | Server |
| Client Component | Browser |
| Dimension | CSR | SSG | ISR | SSR |
|---|---|---|---|---|
| Infra complexity | Lowest — static hosting, no server runtime | Lowest — build once, serve static | Low-medium — needs a regeneration trigger | Highest — a server renders on every request |
| Operational cost | Lowest | Lowest | Low, scales with regeneration frequency | Scales directly with traffic |
| Initial render performance | Slowest — blank until JS loads and fetches | Fastest — pre-built HTML from a CDN | Fast — same as SSG between regenerations | Fast, but bounded by server + data-fetch latency |
| Interaction quality* | Excellent — fully client-owned | Typically low — static content pages | Typically low-to-medium | Good, but hydration cost matters |
| Scalability | Trivial — CDN serves static assets | Trivial — CDN serves static assets | High — most requests hit the cache | Requires scaling server compute with traffic |
| Developer experience | Simplest mental model, no server concerns | Simple, but content goes stale between builds | More moving parts — cache invalidation to reason about | Most powerful, but couples rendering to server infra |
| Ideal use cases | Internal tools, dashboards, desktop-like apps | Marketing sites, docs, blogs | Product catalogs, news, e-commerce | Authenticated 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.
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 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.
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.
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.
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.
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.
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.
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.
Only the interactive components — QuantitySelector, AddToCart and ImageZoom — are shipped to the browser.
Direct database access
const product = await db.product.findUnique(...)No REST endpoint. No JSON serialization. No client fetch.
Server-only code never reaches the browser
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.
Five steps, one goal: match the environment to the experience
What's the dominant UX?
Consumption optimizes the initial render. Manipulation optimizes the interaction loop.
Can everyone get the same initial HTML?
Yes → SSG or ISR become candidates. No → you need SSR or CSR.
How often does it change?
Rarely → SSG. Regularly → ISR. Effectively every request → SSR.
Which parts need continuous interaction?
Decided per feature, not per page — some parts of a page can be interactive while the rest isn't.
Which environment serves each feature best?
Server Component by default. Client Component only when the interaction demands it.
Four things senior engineers still get wrong
SSR is always better than CSR.
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.
RSC replaces Client Components.
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.
Interactive applications should automatically use Server Components.
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.
SEO should be the first architectural question.
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.