CSR vs SSR vs SSG vs ISR
Modern web apps use four main rendering strategies. Understanding when to use each — Client-Side Rendering, Server-Side Rendering, Static Site Generation, and Incremental Static Regeneration — is key to building fast web apps.
Why Rendering Strategy Matters
How a page is rendered affects:
- Performance — Time to First Byte (TTFB), First Contentful Paint (FCP)
- SEO — Can search engines read the content?
- User experience — Does the page feel fast and interactive?
- Infrastructure cost — Do you need a server running 24/7?
There are four main strategies, each with trade-offs.
1. Client-Side Rendering (CSR)
The server sends a nearly empty HTML shell. JavaScript downloads, runs in the browser, and renders the page.
<!-- What the server sends -->
<!DOCTYPE html>
<html>
<head><title>My App</title></head>
<body>
<div id="root"></div> <!-- empty! -->
<script src="/bundle.js"></script>
</body>
</html>
// React takes over and renders the full page
ReactDOM.createRoot(document.getElementById("root"))
.render(<App />);
Timeline:
Browser requests page
→ Server responds: minimal HTML
→ Browser downloads JS bundle (may be large)
→ JS executes, renders the page
→ User sees content
→ Additional API calls for data
Pros:
- Simple deployment (serve static files)
- Fast subsequent navigation (SPA — no full page reload)
- Great for highly interactive apps
- Cheap hosting (no server needed)
Cons:
- Poor SEO (crawlers may not run JS, or run it slowly)
- Slow initial page load (empty HTML until JS runs)
- Poor performance on slow networks/devices
Best for: Dashboards, admin tools, apps behind authentication where SEO doesn't matter.
2. Server-Side Rendering (SSR)
For each request, the server renders the full HTML with data and sends it to the browser.
// Next.js example
export async function getServerSideProps(context) {
const { params, req } = context;
const data = await fetchFromDatabase(params.id);
return {
props: { data }, // passed to the component
};
}
export default function Page({ data }) {
return <div>{data.title}</div>; // HTML rendered on server
}
Timeline:
Browser requests /products/123
→ Server fetches data from DB
→ Server renders HTML with data
→ Server sends complete HTML
→ User sees content (fast!)
→ JS downloads and "hydrates" the page
→ Page becomes fully interactive
Pros:
- Excellent SEO (complete HTML sent)
- Fast First Contentful Paint (user sees real content immediately)
- Always fresh data
- Works well for user-specific content
Cons:
- Requires a server (more infrastructure + cost)
- Higher Time to First Byte (server must render before responding)
- Can't be cached as aggressively as static files
- More complex deployment
Best for: E-commerce product pages, social media feeds, news sites, anything SEO-critical with dynamic per-user or frequently-changing data.
3. Static Site Generation (SSG)
Pages are rendered at build time, not request time. The output is static HTML files that can be served from a CDN.
// Next.js example
export async function getStaticProps() {
const posts = await fetchAllBlogPosts();
return { props: { posts } };
}
export async function getStaticPaths() {
const posts = await fetchAllBlogPosts();
return {
paths: posts.map(p => ({ params: { slug: p.slug } })),
fallback: false,
};
}
export default function BlogPost({ post }) {
return <article>{post.content}</article>;
}
Timeline:
BUILD TIME: All pages rendered → dist/ folder with HTML files
REQUEST TIME:
Browser requests /blog/my-post
→ CDN serves pre-built my-post.html (instant! ~1ms)
→ User sees content immediately
→ JS hydrates
Pros:
- Fastest possible page load (CDN-served static HTML)
- Best SEO
- Cheapest to host (no server, just CDN)
- Highly scalable
- Excellent security (no server to attack)
Cons:
- Data can become stale (site must be rebuilt for updates)
- Long build times for large sites (10,000+ pages)
- Can't serve user-specific content
- Not suitable for real-time data
Best for: Marketing sites, blogs, documentation, landing pages — anything where content changes infrequently.
4. Incremental Static Regeneration (ISR)
ISR is a Next.js innovation: static pages that automatically regenerate in the background when the content changes. Best of both SSG and SSR.
// Next.js example — same as SSG but with revalidate
export async function getStaticProps() {
const post = await fetchPost();
return {
props: { post },
revalidate: 60, // regenerate at most once per 60 seconds
};
}
Timeline:
First request: serve stale static HTML (instant)
trigger background regeneration
Second request (after 60s): serve fresh regenerated HTML
Pros:
- Static file performance (served from CDN)
- Data can be refreshed without full rebuild
- Handles content updates gracefully
- Works with large sites (only regenerate changed pages)
Cons:
- Slight staleness (content is at most
revalidateseconds old) - More complex mental model
- Next.js-specific (though other frameworks are adding similar features)
Best for: Product catalogs, news articles, content that changes periodically but not in real-time.
Choosing the Right Strategy
| Scenario | Strategy | Why |
|---|---|---|
| Marketing/landing page | SSG | Never changes, needs fast load + SEO |
| Blog posts | SSG or ISR | Mostly static, rare updates |
| News site | ISR | Frequent updates but not real-time |
| E-commerce PDP | SSR or ISR | SEO + prices/inventory change |
| User dashboard | CSR | Auth-required, real-time data, no SEO needed |
| Social feed | SSR | User-specific, real-time |
| Documentation | SSG | Stable content, needs SEO |
| Admin panel | CSR | Behind auth, rich interactivity |
Hybrid Rendering
Modern frameworks let you mix strategies per page:
// Next.js App Router — choose per component/page
// app/page.js (SSG by default)
export const revalidate = 3600; // ISR: regenerate every hour
// app/products/[id]/page.js (SSR — dynamic data)
export const dynamic = "force-dynamic";
// app/dashboard/page.js (CSR — behind auth)
"use client"; // this and all children render on client
Key Takeaways
- CSR: browser renders everything — simple but slow initial load and bad SEO
- SSR: server renders per request — great SEO and fresh data but needs a server
- SSG: rendered at build time — fastest load, best for static content
- ISR: static files that auto-regenerate — combines SSG speed with SSR freshness
- Most real apps use a mix — static for marketing, SSR for SEO-critical dynamic pages, CSR for dashboards
Ready to test your knowledge?
Take a quiz on what you just learned.