// LOADING
// LOADING
// LOADING_ARTICLE
You're building a Next.js app. Your PM asks: "Will this be fast?" Half the room debates SSR vs SSG. Nobody mentions ISR.
This isn't a binary choice. It's a spectrum. Picking wrong costs you real money, users, and time debugging performance issues.
Let me show you how I actually think through this decision.
SSG and SSR aren't just rendering modes—they're architectural commitments with cascading effects.
SSG commits to:
SSR commits to:
ISR (the unicorn):
This is what most frameworks miss. It's about how often content changes.
If content changes faster than your revalidation window, SSR wins.
SSG breaks when personalization is involved due to long build times.
The Rule: If you need context.query or context.headers, go SSR.
Different pages need different freshness levels:
Result: 95% of traffic hits CDN cache, average TTFB: 40ms.
javascript// pages/architecture-decision.jsx export default function ArchitectureDecision({ contentType, changeFrequency, userCount, personalizedContent }) { const renderingStrategy = () => { if (!personalizedContent && changeFrequency === 'monthly') { return { mode: 'SSG', revalidate: 86400 * 30, cost: 'Minimal', reasoning: 'Static hosting' }; } if (!personalizedContent && changeFrequency === 'daily') { return { mode: 'ISR', revalidate: 3600, cost: 'Low', reasoning: 'Fresh, background regeneration' }; } if (personalizedContent || changeFrequency === 'hourly') { return { mode: 'SSR', revalidate: 0, cost: 'High', reasoning: 'Needs computation on every request' }; } if (personalizedContent && userCount > 100000 && changeFrequency === 'realtime') { return { mode: 'Edge Rendering', revalidate: 0, cost: 'Very High', reasoning: 'Compute at edge' }; } return { mode: 'Hybrid', revalidate: 'Variable' }; }; return renderingStrategy(); }
javascriptexport default function ProductPage({ product, stock, reviews }) { return ( <> <h1>{product.name}</h1> <p>{product.description}</p> <StockIndicator count={stock} /> {/* Real-time */} <ReviewSection reviews={reviews} /> {/* Real-time */} <AddToCartButton /> {/* Real-time */} </> ); } export async function getStaticProps({ params }) { const product = await db.products.findBySlug(params.slug); return { props: { product }, revalidate: 1800 }; // Regenerate every 30 mins }
javascriptexport default function ArticlePage({ article }) { return ( <article> <h1>{article.title}</h1> <p>{article.content}</p> <time>{article.publishedAt}</time> </article> ); } export async function getStaticProps({ params }) { const article = await db.articles.findBySlug(params.slug); if (!article) return { notFound: true }; return { props: { article }, revalidate: 60 }; // Regenerate every minute }
javascriptexport default function Dashboard({ user, stats }) { return ( <div> <h1>Welcome, {user.name}</h1> <StatsCard stats={stats} /> </div> ); } export async function getServerSideProps(context) { const session = await getSession(context); if (!session) return { redirect: { destination: '/login' } }; const user = await db.users.findById(session.userId); const stats = await db.stats.getUserStats(session.userId); return { props: { user, stats } }; }
javascriptexport async function getStaticPaths() { const users = await db.users.findAll(); // 1 million users = 6-hour build return { paths: users.map((u) => ({ params: { id: u.id } })), fallback: 'blocking' }; }
Better: Generate popular ones, fallback for others.
javascriptexport async function getStaticProps() { const post = await db.posts.findById(params.id); return { props: { post }, revalidate: 86400 }; // Too long } // Solution: Shorter revalidation export async function getStaticProps() { const post = await db.posts.findById(params.id); return { props: { post }, revalidate: 300 }; // 5 minutes }
javascriptexport default function Product({ staticPrice, realTimeStock }) { return <h1>Price: ${staticPrice} | Stock: {realTimeStock}</h1>; } // Fix: Fetch both client-side or both server-side
Is the page personalized per user?
├─ YES → SSR only
└─ NO → Continue
Does content change hourly or faster?
├─ YES → SSR or Edge Computing
└─ NO → Continue
Do you have thousands of dynamic pages?
├─ YES → ISR with fallback: 'blocking'
└─ NO → Continue
Is this a public page everyone sees the same?
├─ YES → SSG with ISR revalidation
└─ NO → SSR
SSR vs SSG isn't a religious debate. It's about infrastructure trade-offs.
Pick SSG when you can predict all pages at build time and content changes rarely.
Pick SSR when you need real-time data or personalization.
Use ISR when you're in between—most of the time.
Make informed decisions based on requirements, not last project experience.