Skip to content
Web

ISR vs SSR vs SSG: Choosing the Right Rendering Mode in Next.js

30 June 20266 min read0 views
ISR vs SSR vs SSG: Choosing the Right Rendering Mode in Next.js
A practical breakdown of Next.js rendering strategies — when to use Static Generation, Server-Side Rendering, or Incremental Static Regeneration for real-world pages.

The Rendering Decision

One of the most impactful architectural choices in a Next.js application is deciding how each page gets its HTML. The wrong rendering strategy adds unnecessary server load, increases TTFB, or serves stale data. Next.js App Router offers three fundamental modes:

1. Static Site Generation (SSG)

SSG renders the page at build time. The resulting HTML is cached permanently until the next deployment.

Best for: Marketing pages, documentation, any content that never changes between deploys.

// No fetch calls — all data hardcoded or from build-time imports
export default function AboutPage() {
  return <div>About me</div>
}
// This compiles to a static .html file

Trade-off: Stale data until redeploy. Adding a new portfolio project requires rebuilding the entire app.

2. Incremental Static Regeneration (ISR)

ISR renders statically at build time, but automatically regenerates the page in the background after a revalidate interval.

export const revalidate = 3600 // Regenerate at most once per hour

export default async function ProjectsPage() {
  const projects = await getProjects() // DB fetch runs at build + each revalidation
  return <ProjectList projects={projects} />
}

Best for: Portfolio content, blog indexes, product listings — content that updates occasionally but doesn't need to be real-time.

Trade-off: A user visiting within the stale window gets the cached version. The next visitor after expiry triggers a background regeneration.

3. Server-Side Rendering (SSR)

SSR generates a fresh HTML response for every single request. No caching at the page level.

export const dynamic = 'force-dynamic'

export default async function AdminDashboard() {
  const user = await verifySession()
  const stats = await getRealtimeStats()
  return <Dashboard user={user} stats={stats} />
}

Best for: Authenticated dashboards, admin portals, personalized pages, real-time data feeds.

Trade-off: Higher TTFB since every request hits the server and database.

Decision Framework

| Page Type | Mode | Revalidate | | :--- | :--- | :--- | | Marketing landing page | SSG | — | | Portfolio projects list | ISR | 3600s | | Blog article detail | ISR | 3600s | | Admin dashboard | SSR | force-dynamic | | Real-time analytics | SSR | force-dynamic |

Building a Next.js application that balances performance with data freshness? Let's talk →

Frequently Asked Questions

Q:Can I mix ISR and SSR on different pages in the same Next.js app?

Yes. Each page segment can have its own revalidate value. You can have your homepage use ISR (revalidate=3600) and your admin dashboard use force-dynamic SSR simultaneously.

Q:Does ISR work on Vercel Edge functions?

ISR is primarily a Node.js runtime feature. Edge runtime supports a simpler cache model but not full ISR with background regeneration. Use the Node.js runtime for ISR-heavy pages.

Working on something similar?

Let's collaborate to design custom PCB schematics, write deterministic FreeRTOS threads, or configure secure Next.js databases.

Let's talk →