Web Rendering Strategies Explained: CSR, SSR, SSG, ISR


TLDR;
Making a choice, when it comes to the right rendering strategy to use, all depends on context or use case.
Ask yourself:
How often does this content change?
Who needs to see it; users, crawlers, or both?
What’s more important; speed, SEO, or freshness?
Once you have the answers to these questions, then the right strategy to use at that point in time presents itself. No need to over-engineer. KISS!
You are not alone! 😇
If you’ve tried building or optimizing a frontend web app and felt overwhelmed by all the rendering options (CSR, SSR, SSG, ISR) thrown at you, I’m here to promise you that you are not alone. 😄
This list sounds intimidating at first but once you understand them, their strengths, tradeoffs, and use cases, they become your secret weapon for performance, SEO optimization, and good user experience.
Let’s take a deep dive and get you closer to shipping better web experiences! 😉👍
What is Web Rendering?
Web rendering refers to how the content of your web app or site is bundled into HTML and delivered to the user; either by the browser, the server, or during build.
Different strategies affect performance, SEO, caching, and the user experience as a whole. These strategies include:
1. Client-Side Rendering (CSR)
What:
In this strategy, the entire web app is rendered with JavaScript by the browser. The browser loads a page that is blank or has little content, then JavaScript kicks in, fetches data, and renders everything.
When to use:
Your content is private or personalized (e.g. dashboards, admin panels).
SEO doesn't matter much (e.g. internal tools, web apps behind auth).
You want fast initial page loads after the first visit (thanks to caching).
Cons:
Slower initial load (especially on low-end devices).
SEO-unfriendly (unless paired with dynamic rendering or pre-rendering hacks).
Example (Next.js):
'use client';
export default function DashboardPage() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('/api/data').then(res => res.json()).then(setData);
}, []);
return <div>{/* render data */}</div>;
}
PS: CSR is generally not recommended for good SEO.
2. Server-Side Rendering (SSR)
What:
Here, HTML is generated on the server-side at the time of request by a user. The server fetches the data needed and returns fully rendered HTML to the client.
When to use:
You need up-to-date content on every visit.
SEO is important and the data changes frequently (e.g. product pages with live inventory).
You’re dealing with user-specific content visible to crawlers (e.g. account previews).
Cons:
Slower response compared to static pages.
Server load increases with traffic; the higher the number of active users, the higher the load on the server.
Example (Next.js):
// pages/products.tsx (Pages Router)
type Product = {
id: string;
name: string;
description: string;
};
type Props = {
products: Product[];
};
export default function ProductListPage({ products }: Props) {
return (
<div>
<h1>Product List</h1>
<ol>
{products.map(item => (
<li key={item.id}>{item.name}: ${item.description}.</li>
))}
</ol>
</div>
);
}
export async function getServerSideProps() {
const response = await fetch('https://example.com/api/v1/products');
const products = await response.json();
return { props: { products } };
}
3. Static Site Generation (SSG)
What:
In this case, the HTML is pre-rendered during build. It’s fast, SEO-friendly, and is great for pages that don’t change often.
When to use:
Your content is mostly static (e.g. blog posts, landing pages).
You want a really fast performance with CDN-level caching.
You don’t mind rebuilding your site each time you want updates to reflect.
Cons:
- Not great for real-time data unless paired with revalidation or client-side fetching. This can be seen in the next rendering strategy (ISR).
Example (Next.js):
// pages/posts.tsx (Pages Router)
type Post = {
id: string;
title: string;
};
type Props = {
posts: Post[];
};
export default function BlogPostsPage({ posts }: Props) {
return (
<div>
<h1>Blog Posts</h1>
<ol>
{posts.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ol>
</div>
);
}
export async function getStaticProps() {
const response = await fetch('https://example.com/api/v1/blog-posts');
const posts = await response.json();
return { props: { posts } };
}
4. Incremental Static Regeneration (ISR)
What:
This is a hybrid approach for rendering web pages. The pages are generated statically at build time, and then updated under the hood after a set intervals (or when needed).
When to use:
You want the speed of SSG but with updatable content.
SEO matters, but you don’t want to rebuild your whole site each time you want changes to reflect.
You're working with CMS-driven or eCommerce content (like product details).
Cons:
Slightly complex when it comes to handling stale vs. fresh data.
More difficult to debug when compared to pure SSG or SSR.
Example (Next.js):
// pages/posts.tsx (Pages Router)
type Post = {
id: string;
title: string;
};
type Props = {
posts: Post[];
};
export default function BlogPostsPage({ posts }: Props) {
return (
<div>
<h1>Blog Posts</h1>
<ol>
{posts.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ol>
</div>
);
}
export async function getStaticProps() {
const response = await fetch('https://example.com/api/v1/blog-posts');
const posts = await response.json();
return {
props: { posts },
revalidate: 60, // Regenerate every 60 seconds
};
}
In Summary… When Should I Use What?
Strategy | Best For | SEO | Freshness | Performance |
CSR | Authenticated apps, dashboards | ❌ | ✅ | ⚠️ first load |
SSR | Dynamic pages with frequent updates | ✅ | ✅ | Medium |
SSG | Blogs, marketing pages | ✅ | ❌ (build-time) | 🚀 |
ISR | Product pages, CMS-driven sites | ✅ | ✅ (after delay) | 🚀 + ⏳ |
References & Further Reading
PS: Like, comment and share if this helps you. Also, comment areas that may not be so clear to you yet (whether implementation wise, or you want examples in other frameworks) and I’ll do my best to drop more notes on that.
Also worthy of note;
You can use a mix; In frameworks like Next.js, you can mix strategies per route. For instance,
/about
can be SSG,/dashboard
can be CSR, and/product/[id]
can use ISR.You should measure first; Don’t blindly choose SSG for SEO. Sometimes SSR + cache does the job better.
Thank you and see you in the next one! 😉😇
Subscribe to my newsletter
Read articles from Gospel Chinyereugo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
