Static Site Generation (SSG) Patterns: Architecting for Performance
Master Static Site Generation (SSG) and Incremental Static Regeneration (ISR) to shift rendering to build time and deliver lightning-fast, scalable React apps.
Previously in this course, we explored Streaming Server-Side Rendering to improve Time to First Byte (TTFB) by flushing HTML incrementally. While streaming SSR excels at dynamic, user-specific data, it still incurs a server-side cost for every request. This lesson introduces Static Site Generation (SSG), a pattern that trades runtime server cycles for near-instant delivery by moving rendering to build time.
Understanding Static Generation from First Principles
At its core, SSG means generating the HTML for a page at build time rather than at request time. When a user requests a static page, the server (or CDN) simply serves a pre-rendered file.
This eliminates the "cold start" of server-side logic, database queries, and component reconciliation for every request. The result is a performance profile that is essentially limited only by the speed of your CDN.
SSG vs. SSR Comparison
| Feature | Static Site Generation (SSG) | Server-Side Rendering (SSR) |
|---|---|---|
| Rendering Time | Build Time | Request Time |
| Data Freshness | Stale until next build | Real-time |
| Server Load | Extremely Low (CDN heavy) | High (Compute heavy) |
| Use Case | Blogs, Marketing, Docs | Dashboards, User feeds |
Implementing SSG Patterns
In a modern React framework (like Next.js), you implement SSG by defining how a page fetches data during the build process. Instead of fetching data inside useEffect or relying on runtime SSR functions, you use build-time data hooks.
Worked Example: Generating a Static Product Catalog
Imagine we are building a product catalog for our project. We want the product pages to be as fast as possible. We use getStaticProps (or equivalent build-time functions) to fetch the data once when the site is deployed.
JAVASCRIPT// pages/products/[id].js // This function runs at build time export async function getStaticProps({ params }) { const product = await fetchProductFromAPI(params.id); return { props: { product }, // Incremental Static Regeneration: Re-validate every 60 seconds revalidate: 60, }; } // This function tells the build system which paths to pre-render export async function getStaticPaths() { const products = await getAllProductIds(); const paths = products.map((id) => ({ params: { id } })); return { paths, fallback: CE9178">'blocking' }; } export default function ProductPage({ product }) { return <div>{product.name} - {product.price}</div>; }
Managing Incremental Static Regeneration (ISR)
The biggest drawback of pure SSG is that updating content requires a full site rebuild. If you have 10,000 product pages, a rebuild for a price change is inefficient.
ISR solves this by allowing you to update static pages in the background after the site is deployed. By adding a revalidate property to your build-time logic, you tell the server: "If a request comes in after X seconds, serve the cached version, but trigger a background regeneration of this page."
This gives you the best of both worlds: the performance of static files and the flexibility of dynamic updates.
Hands-on Exercise: Static Optimization
- Audit your current project: Identify three pages that do not contain user-specific data (e.g., "About Us," "Help Center," or a public product list).
- Refactor: Move the data fetching logic for these pages from
useEffectinto a build-time data function. - Configure ISR: Set a
revalidatewindow (e.g., 3600 seconds for one hour) to ensure your content stays fresh without needing a redeploy for minor updates. - Verify: Run a production build (
npm run build) and inspect the output. You should see static HTML files generated for these routes.
Common Pitfalls
- Over-using ISR: Don't set
revalidateto 1 second for highly volatile data. Use it for content that changes periodically. If you need true real-time updates, use client-side fetching with React Query instead. - Assuming User Context: You cannot access cookies, headers, or local storage during SSG because the page is generated on a build server, not the user's device. If a page requires user authentication, it cannot be fully static.
- Large
getStaticPaths: If you have millions of pages, building them all at once will crash your build pipeline. Usefallback: 'blocking'to generate pages on-demand the first time they are requested, rather than pre-building every single possible route.
Recap
SSG turns your React application into a set of highly optimized static files. By leveraging getStaticPaths to define your routes and revalidate to manage content freshness through ISR, you can scale your application to handle massive traffic with minimal compute cost. Remember to balance the need for performance against the need for data freshness when deciding between SSG and SSR.
Up next: We will explore Internationalization (i18n) Architecture, focusing on how to manage localized content without destroying your performance gains.
Work with me

Next.js Full-Stack Web App Development
A fast, SEO-ready full-stack web app built with Next.js 16 โ from idea to deployed product, by an engineer who ships to production.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds โ familiar editing, modern speed.