Why static and dynamic no longer have to be a trade-off

Web teams have long had to choose between the speed of static delivery and the flexibility of dynamic rendering. Partial Prerendering (PPR), introduced with Next.js 14 on Vercel, aims to remove that choice by combining edge-cached static shells with streaming dynamic content in a single request model.

The core idea is simple: prerender as much of a page as possible at build time, while leaving holes that the server fills at request time based on cookies, headers, or other user-specific inputs. The result is a page that starts rendering instantly from the nearest edge region while the server concurrently streams the dynamic chunks.

For teams evaluating rendering strategies, PPR attempts to bridge the gap between existing approaches:

This table shows the features of common rendering strategies compared to the features of PPR, which eliminates trade-offs experienced in other methods. This table shows the features of common rendering strategies compared to the features of PPR, which eliminates trade-offs experienced in other methods.

A single React tree, with dynamic boundaries where you choose

PPR does not introduce a separate templating language or a parallel rendering path. In Next.js, rendering still occurs within one React tree. Static optimization is enabled by default for every component, until the application accesses request-specific data such as headers or cookies. At that point, Next.js automatically marks the closest <Suspense> boundary as dynamic, leaving all outer content statically optimized.

This differs from older techniques like server-side includes, which treated static and dynamic content as separate technology worlds with no mechanism for incremental updates to static regions.

Consider a typical ecommerce product page:

export default function Page() {

return (

<main>

<header>

<h1>My Store</h1>

<Suspense fallback={<CartSkeleton />}>

<ShoppingCart />

</Suspense>

</header>

<Banner />

<Suspense fallback={<ProductListSkeleton />}>

<Recommendations />

</Suspense>

<NewProducts />

</main>

);

}

With PPR enabled, the page is built as a static shell from your <Suspense> boundaries. The fallbacks you provide to React Suspense are prerendered. When a user visits, the shell is served from the edge while dynamic components—such as a cookie-based cart count or a personalized promotional banner—are rendered and streamed in to replace those fallbacks.

How the build and runtime behave

During the build, Next.js prerenders a static shell for each route and leaves holes at Suspense boundaries that need dynamic data. When a request arrives, the shell is served from the user's nearest edge region. The browser can immediately begin parsing HTML, stylesheets, fonts, and scripts, even as the server streams dynamic chunks using React's streaming architecture.

Under the hood, PPR inherits the strengths of two existing rendering models:

  • Incremental Static Regeneration (ISR) keeps the static shell updatable via on-demand, time-based, or tag-based revalidation.
  • Server-Side Rendering (SSR) supplies the dynamic capability. Accessing cookies or other request features automatically switches rendering to dynamic, up to the nearest Suspense boundary.

Because the Suspense boundary is the control point, you determine which parts stay static and which become dynamic—no separate code paths are required.

Not restricted to content-heavy pages

PPR fits applications across the static/dynamic spectrum. A dashboard that is mostly dynamic with a minimal shell works as well as a content page where only small elements, such as reviews or recommendations, must be personalized.

In the product detail page demo, almost all content is part of the static prerender. Only customer reviews, the shopping cart count, a delivery-time estimate based on zip code, and recommendations below the fold are streamed dynamically.

In that wireframe, purple marks typically static regions and blue marks dynamic regions. PPR lets the vast majority of such a page be served straight from the edge. And since the shell is built on ISR, the same revalidation methods available today—on-demand, time-based, and tag-based—apply to the static content.

Framework-agnostic at the infrastructure level

When used on Vercel, PPR relies on framework-defined infrastructure primitives that any frontend framework can adopt through Vercel's Build Output API. Framework authors interested in integrating PPR can work directly with Vercel to add support.

Trying the experimental preview

A preview of PPR is available in the latest Next.js 14 canary release with the app directory. Enable it by adding the following to your next.config.js:

experimental: {

ppr: true,

},

Alternatively, a ready-made template provides a starting point.

Note that this is an experimental technology and is not yet recommended for production use. Larger code bases may encounter developer experience issues, and known limitations remain—for example, client-side navigations do not yet perform a streaming render.