React Server‑Side Rendering vs Static Generation: How to Choose in 2026
Understand when to choose React SSR vs Static Generation. Compare performance, SEO, caching, costs, and patterns like streaming SSR, ISR, and RSC.
Image used for representation purposes only.
Why this comparison matters
Choosing between server-side rendering (SSR) and static site generation (SSG) in React directly affects performance, SEO, cost, and your team’s velocity. Modern React gives you multiple levers—streaming SSR, partial hydration, React Server Components (RSC), and incremental/static regeneration—to build the right mix. This article breaks down the trade‑offs and offers a practical decision framework, with code snippets you can adapt today.
Quick definitions
- Server‑Side Rendering (SSR): HTML is rendered on demand for each request on a server or edge runtime, then hydrated on the client.
- Static Site Generation (SSG): HTML is prebuilt at build/deploy time and served from a CDN. Hydration still happens on the client.
- Hybrid: Combine both. For example, most pages are static, while dashboards and checkout use SSR. Variants include incremental/static regeneration (ISR) and on‑demand revalidation.
How rendering works under the hood
- Initial HTML
- SSR: The server runs your React tree, turns it into HTML, and streams or sends it to the browser. Time‑to‑first‑byte (TTFB) includes network + server compute.
- SSG: HTML is generated during the build. TTFB is primarily network latency from the nearest CDN node.
- Hydration
- Both SSR and SSG ship JavaScript that reattaches event listeners and makes the page interactive. With React Server Components, parts of the tree never hydrate, reducing JS shipped to the client.
- Data fetching
- SSR: Fetch runs per request (or per cache window) on the server. Great for highly dynamic or personalized data.
- SSG: Fetch runs at build time. Great for content that changes infrequently. With ISR/on‑demand revalidation, you can refresh prebuilt pages on a schedule or trigger.
Performance: what actually changes for users
- TTFB
- SSG usually wins because HTML is already built and CDN‑cached.
- SSR can be competitive with edge runtimes and aggressive caching, but compute and origin distance still matter.
- LCP (Largest Contentful Paint)
- Both approaches can deliver fast LCP if the main content is in server‑rendered HTML. Heavy client bundles and late-loading images are common bottlenecks.
- Interactivity (TTI/INP)
- Hydration cost dominates. Reduce JS with RSC, code-splitting, and deferring noncritical scripts. Static vs server‑rendered HTML does not, by itself, guarantee faster interactivity.
- Streaming SSR
- Streaming lets the server flush the shell early and progressively send content as data resolves. Users see meaningful content sooner, even when downstream calls are slow.
SEO, sharing, and analytics
- SSR and SSG both produce indexable HTML at first paint, which search engines can crawl reliably.
- SSG often achieves superior crawl efficiency due to low latency and predictable URLs cached at the edge.
- SSR helps when content is personalized for bots (usually not recommended) or when the page depends on fast‑expiring data you want indexed immediately.
- For social sharing, both approaches provide stable meta tags in the HTML; ensure your Open Graph/Twitter tags are part of the server‑rendered output.
Data freshness and personalization
- Use SSR when
- The page is user‑specific (cart totals, dashboards, subscriptions).
- Data changes minute‑to‑minute and must be reflected on first paint (e.g., pricing, inventory) without client refetch.
- Use SSG when
- Content is editorial or catalog‑like and can tolerate minutes to hours of staleness.
- You can push updates through ISR or on‑demand revalidation hooks.
Caching strategy is the real differentiator
- SSG caching
- CDN caches HTML indefinitely. Rebuild or revalidate to refresh. Immutable asset hashing simplifies cache busting.
- SSR caching
- Leverage HTTP cache headers (Cache‑Control, Vary) and set short TTLs with stale‑while‑revalidate to hide server latency.
- Split the page into cacheable fragments (Edge/CDN) and noncacheable personalized sections (rendered per request) using RSC or streaming.
Cost, complexity, and reliability
- Build costs (SSG)
- Scale with the number of pages and data sources. Very large catalogs can lead to long builds. ISR alleviates this by generating on first request and caching the result.
- Runtime costs (SSR)
- Scale with traffic and compute per request. Spiky loads may require autoscaling or edge rendering. Cold starts matter on some platforms.
- Operational surface area
- SSR: more moving parts—secrets, retries, timeouts, observability, and backpressure on downstream APIs.
- SSG: simpler deployments and rollback (atomic), stronger cache hit ratios, fewer runtime surprises.
Tooling patterns you’ll use
- React 18 streaming SSR with Suspense for progressive rendering.
- React Server Components to ship less client JavaScript and keep data‑fetching on the server.
- Incremental/On‑Demand Static Regeneration to refresh static pages without a full rebuild.
- Edge rendering for lower latency and fine‑grained caching near users.
A practical decision framework
Ask these questions per route:
- How personalized is the content?
- High (user‑specific): Prefer SSR or client fetch behind an authenticated shell. Consider server components to avoid shipping secrets.
- Low/none: Prefer SSG.
- How fresh must the content be on first paint?
- Seconds/minutes: SSR with short‑TTL caching or edge SSR. Consider streaming.
- Hours/days: SSG with ISR (revalidate N seconds) or on‑demand revalidation.
- How big is the page set and how often does it change?
- Huge catalog with sporadic updates: SSG with ISR/on‑demand revalidation to avoid monolithic builds.
- Small to medium, frequent updates: Either; choose based on personalization and performance goals.
- What’s the acceptable operational complexity?
- Minimal ops and predictable costs: SSG‑first.
- Willing to manage runtime compute for dynamic features: SSR where it adds user value.
Code examples
The following snippets illustrate the core ideas. Adapt to your framework of choice.
Streaming SSR (Node + React 18)
import http from 'node:http';
import React from 'react';
import { renderToPipeableStream } from 'react-dom/server';
import App from './App.js';
const server = http.createServer((req, res) => {
let didError = false;
const stream = renderToPipeableStream(<App url={req.url} />, {
onShellReady() {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.statusCode = didError ? 500 : 200;
res.write('<!DOCTYPE html>');
stream.pipe(res);
},
onError(err) {
didError = true;
console.error(err);
}
});
// Optional: abort if upstream APIs are too slow
setTimeout(() => stream.abort(), 10000);
});
server.listen(3000);
Static Generation with incremental revalidation (Next‑style)
// pages/products/[slug].js
export async function getStaticPaths() {
const slugs = await getAllProductSlugs();
return { paths: slugs.map((s) => ({ params: { slug: s } })), fallback: 'blocking' };
}
export async function getStaticProps({ params }) {
const product = await getProduct(params.slug);
return {
props: { product },
// Rebuild this page in the background at most once per 60 seconds
revalidate: 60,
};
}
export default function ProductPage({ product }) {
return (
<main>
<h1>{product.title}</h1>
<p>{product.priceFormatted}</p>
</main>
);
}
Common anti‑patterns (and fixes)
- Rendering everything with SSR “for SEO”
- Fix: Prefer SSG for stable content. Use SSR only where freshness/personalization requires it.
- Shipping the same large client bundle for SSR and SSG pages
- Fix: Code‑split, move logic to server components, and defer noncritical widgets.
- Treating caches as an afterthought
- Fix: Design caching up front—TTL, revalidation paths, Vary keys, and cache partitioning.
- Building the entire catalog on every commit
- Fix: ISR or on‑demand revalidation keyed to the changed entries only.
Monitoring and budgets
Track these per route:
- TTFB (edge and origin), LCP, CLS, INP
- Cache hit ratio (CDN and application cache)
- Hydration time and total JS shipped
- Error rate/timeouts for upstream data
- Build times and revalidation latency Set performance budgets (e.g., LCP < 2.5s on 4G, JS < 150KB for critical route) and enforce them in CI.
Migration strategies
- SSR → SSG
- Identify routes with low personalization and predictable data. Add static generation with ISR. Measure reduced TTFB and server load.
- SSG → SSR
- For dashboards and heavily dynamic flows, render on the server, but keep global chrome and marketing pages static.
- Hybridize with RSC
- Move data‑heavy, noninteractive components to the server; keep interactive islands small and client‑only.
Recommendations by scenario
- Marketing site, docs, blog
- SSG with full CDN caching; ISR for scheduled updates; sprinkle client interactivity as islands.
- Product catalog with price/stock that changes hourly
- SSG with short revalidation (e.g., 60–300s). Push urgent changes via on‑demand revalidation webhooks.
- Authenticated dashboards and carts
- SSR or edge SSR with streaming; cache public fragments; fetch user‑specific data server‑side.
- News, live data, or rapidly expiring promos
- SSR with aggressive, short‑TTL caching and streaming; consider edge rendering near users.
Key takeaways
- SSG maximizes cacheability, reliability, and cost predictability. It’s ideal for stable, public content at scale.
- SSR excels when you need per‑request data or personalization at first paint. Streaming and RSC help you keep it fast.
- Most production apps win with a hybrid: static by default, server‑render where it matters, and revalidate intelligently.
- Decide per route and back your choice with metrics, not dogma.
Related Posts
React Hydration Mismatch: A Practical Debugging Guide
Learn how to diagnose and fix React hydration mismatches with step-by-step checks, common causes, and production-safe patterns for SSR and Next.js.
React Suspense Data Fetching Patterns: From Waterfalls to Progressive Rendering
A practical guide to React Suspense data fetching—patterns, boundaries, caching, streaming SSR, and real-world code examples.
React SEO Optimization: A Practical Next.js Guide
A practical Next.js SEO guide for React: metadata, SSR/SSG, canonicals, sitemaps, schema, i18n, Core Web Vitals, and production checklists.