Partial Prerendering (PPR) lets one route have a static shell plus dynamic parts. It solves the problem that one dynamic piece used to make the whole page dynamic.
The problem. Before PPR, a whole route was either static or dynamic. Say you call cookies() once, to show a cart count. Then the entire page renders per request. It loses the CDN speed of a static page.
How PPR works.
- At build time, Next.js prerenders a static shell. This is everything outside Suspense boundaries that doesn't need request data.
- At request time, the server sends that shell at once.
- The dynamic parts, wrapped in
<Suspense>, stream in within the same response.
The Suspense boundary (the <Suspense> wrapper) is the line between static and dynamic. Picture a printed form with blank boxes: the form is ready in advance, and the boxes get filled in per visitor.
Versions. In Next.js 15, PPR was experimental. In Next.js 16, this model is what you get with Cache Components (cacheComponents: true).
- PPR gives one route a static shell with dynamic holes.
- The shell is prerendered and sent at once.
- Dynamic parts stream in inside Suspense boundaries.
- One dynamic API no longer makes the whole page dynamic.
- PPR was experimental in Next.js 15 and is part of Cache Components in 16.