PPR vs SSR vs SSG vs ISR in Next.js: Complete Comparison

How Partial Prerendering, server-side rendering, static site generation, and incremental static regeneration differ in Next.js 16, and which to choose.

8 min read

PPR, SSR, SSG, and ISR are the four rendering strategies you meet in Next.js documentation and job postings. In the App Router they have newer names: server-side rendering is dynamic rendering, static site generation is static rendering, and incremental static regeneration is revalidation. Partial Prerendering changed the most, because it is no longer a per-route opt-in.

These are not four buttons you pick between. Next.js chooses the strategy for each part of a route based on the APIs you use.

This article assumes Cache Components, enabled with cacheComponents: true in next.config.ts. That flag is opt-in, and turning it on makes Partial Prerendering the default rendering model for every route.

The four strategies at a glance

The difference that matters is when the HTML is produced and how fresh the data can be.

StrategyRenderedFresh dataServed from
SSRPer requestYesThe server
SSGAt build timeOnly after redeployCDN
ISRAt build time, then revalidatedAfter the revalidate windowCDN, with background refresh
PPRStatic shell at build time, rest at requestPer boundaryCDN shell, then streamed

SSR is the slowest per request but always fresh. SSG is the fastest and cheapest but frozen until the next deploy. ISR and PPR combine the two, which is why modern Next.js leans on them.

What each term means in the App Router

Server-side rendering used to be a mode you enabled for a whole page. In the App Router the equivalent is dynamic rendering, and it happens when a component reads a request-time API or uncached data.

App.tsxApp.tsx
// app/time/page.tsx
import { connection } from 'next/server'
import { Suspense } from 'react'
 
async function Clock() {
  await connection()
  return <p>{new Date().toISOString()}</p>
}
 
export default function TimePage() {
  return (
    <Suspense fallback={<p>Loading time...</p>}>
      <Clock />
    </Suspense>
  )
}

connection() tells Next.js to wait for a real request before continuing, so the timestamp is never baked into the shell. The browser gets the fallback first and the timestamp streams in. There is no ssr: true flag to set, the use of request-time data makes the decision, and the Suspense boundary is what keeps the rest of the route prerenderable.

Static site generation is the same idea from the other side. A page that uses only build-time data prerenders to HTML and never runs again until the next deploy.

ISR and PPR close the gap

ISR keeps the speed of static HTML while allowing updates. A page is prerendered, then rebuilt in the background when its revalidation window passes or when you invalidate it on demand. For the full walkthrough, see Incremental Static Regeneration.

PPR goes further and splits a single route. The static shell ships instantly from a CDN, and the dynamic parts stream in when ready.

You do not enable PPR in Next.js 16, it is the default under Cache Components. For the pipeline, see how Partial Prerendering works.

Which one should you use

Choose by how often the content changes and whether it depends on the visitor.

  • Static content that rarely changes: static rendering.
  • Content that changes a few times a day: ISR or a cached function.
  • Per-visitor or per-request content: dynamic rendering inside a Suspense boundary.
  • A page that mixes all three: PPR, which you get by default.

The common mistake is thinking you must lock a page to one strategy. In Next.js 16 the honest answer is usually a mix, and the framework builds that mix for you.

Rune AI

Rune AI

Key Insights

  • SSR maps to dynamic rendering in the App Router.
  • SSG maps to static rendering at build time.
  • ISR is revalidation, rebuilding static pages in the background.
  • PPR mixes a static shell with streamed dynamic content and is the default once Cache Components is enabled.
  • The strategy is chosen by the APIs you use, not by one config flag.
RunePowered by Rune AI

Frequently Asked Questions

Is SSR still a thing in the App Router?

Yes, but it is called dynamic rendering. A component renders per request when it reads request-time APIs or uncached data.

Does PPR replace ISR?

No. PPR decides what is static within one route. ISR decides when a prerendered route gets rebuilt, and the two work together under Cache Components.

Conclusion

PPR, SSR, SSG, and ISR are not four competing buttons. In the App Router they are the same rendering system seen from different angles, and Next.js 16 picks the right mix for each route automatically.