SSG vs SSR — When to Use Static Generation vs Server Rendering
In this tutorial, you will learn about SSG vs SSR. We cover key concepts, practical examples, and best practices to help you master this topic.
Static Site Generation and Server-Side Rendering serve different needs: SSG pre-builds at compile time, SSR renders per request. Choose based on content freshness and scale.
What You'll Learn
By the end of this tutorial, you'll understand the key differences between SSG and SSR, the tradeoffs each approach makes, and how to choose the right rendering Strategy for your project.
Why It Matters
Choosing the wrong rendering strategy leads to slow pages, high server costs, or stale content. Understanding the SSG vs SSR tradeoff helps you balance performance, freshness, and infrastructure requirements.
Real-World Use
A news website uses SSG for evergreen articles (always accessible, fast) and SSR for the homepage (needs real-time headlines). The combination delivers both speed and freshness where each matters most.
SSG vs SSR Decision Flow
graph TD
A[New Page Request] --> B{Content changes
frequently?}
B -->|Yes| C{Needs real-time
data per user?}
B -->|No| D[Use SSG]
C -->|Yes| E[Use SSR]
C -->|No| F{Page count
under 100K?}
F -->|Yes| D
F -->|No| G[Use ISR]
D --> H[Pre-build HTML]
E --> I[Render per request]
H --> J[CDN Cache]
I --> J
J --> K[User Browser]
style D fill:#27ae60,color:#fff
style E fill:#e67e22,color:#fff
style G fill:#3498db,color:#fff
Performance Comparison
// SSG: Build-time rendering
// Content fetched once at build time
export async function getStaticProps() {
const start = Date.now();
const data = await fetch('https://api.example.com/posts');
const posts = await data.json();
console.log(`Build-time fetch: ${Date.now() - start}ms`);
return {
props: { posts }
// No revalidate — fully static
};
}
// SSR: Request-time rendering
// Content fetched on every request
export async function getServerSideProps(context) {
const start = Date.now();
const data = await fetch('https://api.example.com/posts');
const posts = await data.json();
console.log(`Request-time fetch: ${Date.now() - start}ms`);
return {
props: { posts }
};
}
Output:
SSG: Build-time fetch: 450ms (runs once, serves millions)
SSR: Request-time fetch: 450ms (runs per visitor, per visit)
Infrastructure Comparison
// SSG deployment: static files on CDN
const ssgSetup = {
hosting: 'Static file server or CDN (Netlify, Vercel, S3)',
server: 'None required',
scaling: 'Automatic — CDN handles traffic',
cost: 'Low — static hosting is cheap',
buildServer: 'Required for rebuilds'
};
// SSR deployment: server required
const ssrSetup = {
hosting: 'Node.js server (Vercel, AWS, DigitalOcean)',
server: 'Required — renders on each request',
scaling: 'Manual or auto-scaling group',
cost: 'Higher — server compute per request',
buildServer: 'Optional (only for code changes)'
};
Content Freshness Tradeoff
// SSG: Stale until rebuild
function StaleTimeExample({ lastBuild }) {
const minutesSinceBuild = Math.floor(
(Date.now() - new Date(lastBuild).getTime()) / 60000
);
const status = minutesSinceBuild > 60 ? 'stale' : 'recent';
return (
<div className={status}>
<p>Last build: {lastBuild}</p>
<p>Content age: {minutesSinceBuild} minutes</p>
{status === 'stale' && <p>Trigger rebuild for fresh content</p>}
</div>
);
}
// SSR: Always fresh
function FreshContentExample({ serverTime }) {
return (
<div>
<p>Rendered at: {serverTime}</p>
<p>Content guaranteed fresh as of this moment.</p>
</div>
);
}
// getServerSideProps provides current time
export async function getServerSideProps() {
return {
props: {
serverTime: new Date().toISOString()
}
};
}
Common Mistakes
- Using SSR when SSG suffices. If content doesn't change per-request, SSG is faster and cheaper. Blog posts, documentation, and marketing pages rarely need SSR.
- Using SSG for authenticated content. If pages depend on who's viewing them, SSR is necessary. SSG produces the same HTML for everyone.
- Ignoring CDN Caching with SSR. SSR without CDN caching defeats its purpose. Always set Cache-Control headers for SSR pages that aren't user-specific.
- Not measuring Time to First Byte (TTFB). SSG TTFB is typically under 100ms from CDN. SSR TTFB can be 200ms-2s depending on server load and data fetching.
- Hybrid approach complexity. Combining SSG and SSR in one app is powerful but adds complexity. Both need separate build configurations, caching strategies, and deployment pipelines.
Practice Questions
- What is the fundamental difference in when SSG vs SSR renders pages?
- Why does SSG scale better than SSR during traffic spikes?
- When would you choose SSR over SSG for a content site?
- How does CDN caching differ between SSG and SSR?
- Can you use both SSG and SSR in the same application?
Challenge: Benchmark SSG vs SSR performance: create a page that displays the current time using both SSG (build-time timestamp) and SSR (request-time timestamp). Measure the difference and explain the tradeoff.
FAQ
Mini Project
Build a simple comparison dashboard: create one page using SSG (pre-built timestamp, static content) and one using SSR (dynamic timestamp per request). Measure and display the load time of each, and write a summary of when each approach is appropriate.
What's Next
You understand the SSG vs SSR tradeoff. Now learn how to implement SSG with Next.js SSG using getStaticProps and getStaticPaths.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro