
CSR vs SSR vs SSG
Three rendering strategies, each with different trade-offs around performance, SEO, and operational complexity.
CSR — Client-Side Rendering
The server sends a minimal HTML shell. The browser downloads JS, renders the app, fetches data, and updates the DOM.
<!-- What the server sends -->
<html>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html> Pros: Simple deployment (static file hosting), rich interactivity after initial load, no server rendering infrastructure needed.
Cons: Slow Time to First Contentful Paint — user sees a blank page until JS loads. Poor SEO for crawlers that don’t execute JS. Large bundles block rendering.
Use when: Dashboards, admin tools, apps behind auth where SEO doesn’t matter.
SSR — Server-Side Rendering
The server renders full HTML on every request and sends it. The client hydrates.
// Next.js
export async function getServerSideProps(context) {
const user = await fetchUser(context.req.cookies.token);
return { props: { user } };
} Pros: Fast FCP — users see content immediately. Good SEO. Can use server-side auth, cookies, databases directly.
Cons: Slower TTFB — server must render before responding. Higher infrastructure cost. Hydration overhead on client.
Use when: E-commerce product pages, news articles, any public content that needs SEO and changes frequently.
SSG — Static Site Generation
HTML is generated at build time. The same files are served to all users from a CDN.
// Next.js
export async function getStaticProps() {
const posts = await fetchAllPosts();
return { props: { posts } };
}
export async function getStaticPaths() {
const posts = await fetchAllPosts();
return {
paths: posts.map(p => ({ params: { id: p.id } })),
fallback: false,
};
} Pros: Instant response from CDN edge. Zero server rendering cost per request. Excellent SEO.
Cons: Stale data between builds. Build time grows with page count. No per-request personalization.
Use when: Marketing sites, documentation, blogs, content that changes infrequently.
ISR — Incremental Static Regeneration
SSG pages that regenerate in the background after a TTL. Next.js-specific.
export async function getStaticProps() {
return {
props: { data: await fetchData() },
revalidate: 60, // regenerate at most once per 60 seconds
};
} Combines CDN speed with reasonably fresh data.
Quick Reference
| SEO | Fresh data | Server cost | Complexity | |
|---|---|---|---|---|
| CSR | No | Yes | Low | Low |
| SSR | Yes | Yes | High | Medium |
| SSG | Yes | No | Minimal | Low |
| ISR | Yes | Partial | Low | Medium |









