
Next.js SSG vs SSR: Static Site Generation and Server-Side Rendering Explained
Choosing the right rendering strategy is critical for balancing load times, search engine indexing (SEO), and server resource costs. Next.js provides three distinct rendering strategies: Static Site Generation (SSG), Server-Side Rendering (SSR), and Incremental Static Regeneration (ISR).
In the modern App Router, Next.js unifies these models under two categories: Static Rendering and Dynamic Rendering. Next.js automatically decides which model to apply based on how components query data.
In this guide, we will analyze these rendering strategies, explain what triggers dynamic rendering, and provide a roadmap for selection.
1. Static Site Generation (SSG)
In Static Site Generation, Next.js renders your pages to static HTML and JSON during the build process (on your CI/CD server). When users visit your site, the server serves these pre-rendered files instantly.
- Best For: Pages that do not change frequently and are identical for all users (e.g., blogs, documentation portals, landing pages).
- Speed: Extremely fast, as files are hosted on CDNs and require no database queries at runtime.
Static Dynamic Routes: generateStaticParams
For routes with dynamic parameters (like app/blog/[slug]/page.tsx), you can pre-generate all pages at build time using the generateStaticParams function:
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts').then((res) => res.json());
return posts.map((post: any) => ({
slug: post.slug,
}));
}
export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
// This fetch is cached automatically during build
const post = await fetch(`https://api.example.com/posts/${slug}`).then((res) => res.json());
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}2. Server-Side Rendering (SSR)
In Server-Side Rendering, Next.js renders the HTML on the server for every single request. When a user visits the page, the server fetches data from your database, constructs the page, and sends the fully rendered page back.
- Best For: Pages displaying highly dynamic, user-specific data (e.g., shopping carts, dashboard panels, user profiles).
- Speed: Slower than SSG because the page cannot be cached on CDNs, and users must wait for database queries to complete.
What Triggers Dynamic Rendering in Next.js?
Next.js automatically flags a route as dynamic if it encounters Dynamic Functions during build evaluation:
- Calling
cookies()orheaders()inside Server Components. - Reading search query parameters (
searchParams) in page props. - Setting a fetch request to disable caching:
const data = await fetch('https://api.example.com/realtime-prices', {
cache: 'no-store',
});3. Incremental Static Regeneration (ISR)
Incremental Static Regeneration bridges the gap between SSG and SSR. It allows you to update static pages in the background after you have built the site, without rebuilding the entire application.
You declare a revalidation window. Next.js serves the cached static page instantly, and if the revalidation window has passed, it builds the updated page in the background, updating the CDN cache.
- Best For: Large websites with thousands of pages where building everything at build time takes too long, but you still want static page speeds.
// Revalidate this page at most once every hour (3600 seconds)
export const revalidate = 3600;
export default async function CatalogPage() {
const products = await fetch('https://api.example.com/products').then((res) => res.json());
return <div>List of products...</div>;
}Rendering Comparison Matrix
| Strategy | Timing | Speed | Server Overhead | SEO Friendly |
| SSG | Build Time | Instant | Minimal | Excellent |
| SSR | Request Time | Moderate | High | Excellent |
| ISR | Mixed (Build + Revalidate) | Instant | Low | Excellent |
How to Choose the Right Strategy
Ask yourself two questions when designing a page:
- Is the data identical for all users?
- Yes: Use Static Rendering (SSG) or ISR.
- No: Use Dynamic Rendering (SSR).
- Does the data change frequently?
- No (e.g., Blog): Use SSG.
- Yes, but background refresh is fine (e.g., Product list): Use ISR.
- Yes, requires real-time accuracy (e.g., Stock ticker): Use SSR.
Conclusion
Next.js App Router provides a unified rendering architecture. By default, it optimizes for static generation. Understanding what triggers dynamic rendering (like cookies, headers, or no-store fetches) allows you to control page caching, minimize server loads, and deliver rapid page speeds.