SSR, SSG, and ISR are different rendering strategies in Next.js, each optimized for different use cases. Understanding when to use each is critical for performance and data freshness.
SSR (Server-Side Rendering) — render on every request: The page is rendered on the server every time a user requests it. The HTML is generated fresh with the latest data.
1// App Router — SSR is the default behavior2async function ProductPage({ params }: { params: { id: string } }) {3 // This runs on every request4 const product = await fetch(`https://api.com/products/${params.id}`, {5 cache: "no-store", // Ensure fresh data every time6 });7 const data = await product.json();89 return (10 <div>11 <h1>{data.name}</h1>12 <p>{data.description}</p>13 <span>${data.price}</span>14 </div>15 );16}
Pros: Always fresh data, good for personalized content Cons: Slower response time (server must render on every request)
SSG (Static Site Generation) — render at build time: The page is rendered once at build time and served as static HTML. Fastest possible response.
1// App Router — static by default when no dynamic functions are used2async function BlogPage() {3 const posts = await fetch("https://api.com/posts");4 const data = await posts.json();56 return (7 <div>8 {data.map(post => (9 <article key={post.id}>10 <h2>{post.title}</h2>11 <p>{post.excerpt}</p>12 </article>13 ))}14 </div>15 );16}
Pros: Fastest response (pre-rendered HTML), great for SEO, low server load Cons: Content is stale until next build
ISR (Incremental Static Regeneration) — static + periodic refresh: A static page that revalidates after a time interval — best of both worlds.
1// App Router — set revalidation interval2export const revalidate = 60; // Revalidate every 60 seconds34async function ProductPage({ params }: { params: { id: string } }) {5 const product = await fetch(`https://api.com/products/${params.id}`);6 const data = await product.json();78 return (9 <div>10 <h1>{data.name}</h1>11 <p>{data.description}</p>12 </div>13 );14}1516// Pages Router equivalent17export async function getStaticProps() {18 const product = await fetchProduct();19 return {20 props: { product },21 revalidate: 60, // seconds22 };23}
How ISR works: First request serves static HTML. After 60 seconds, the next request triggers a background re-render. The current user sees the old page, but once re-rendering completes, subsequent users see the updated page.
When to use each: