On this page
concept

Partial Prerendering

Created 2026-09-08 25 connections

Partial Prerendering

Partial Prerendering (PPR) is a rendering strategy introduced by Next.js that splits a single route into two phases: a build-time static HTML shell served instantly from a CDN edge node, and request-time dynamic segments streamed via React Suspense boundaries into that shell over a single open HTTP connection. It addresses the core ecommerce rendering dilemma — pages with both cacheable content (product copy, images, schema.org markup) and personalised or volatile content (price, stock, cart state) — without requiring a choice between full SSG and full SSR.

How it works

The static shell is a complete HTML document — including <head> metadata and <link rel='preload'> resource hints — generated at build time. According to the Next.js documentation (nextjs.org, version 15.5.25, 2025-08-05), this means LCP image preloading begins with the very first byte delivered, before any dynamic API call is resolved. Dynamic components are wrapped in <Suspense> boundaries; these stream to the client in parallel in a single HTTP request, using chunked transfer encoding (RFC 7230) or HTTP/2 multiplexed streams (nextjs.org, 2025-08-05).

A component is classified as dynamic — and thus forced into a Suspense boundary in PPR mode — when it uses any of: cookies(), headers(), searchParams, connection(), draftMode(), unstable_noStore(), or fetch() with cache: 'no-store' (nextjs.org, 2025-08-05). PPR also restores the Full Route Cache for routes that previously opted out of static generation due to these signals: by isolating the dynamic call inside a Suspense boundary, the shell is cached independently (samcheek.com, 2026-03-25).

On Vercel, PPR routes produce two deployment artifacts: a CDN-cached static asset (the shell) served globally from edge nodes, and an Edge Function or Serverless Function (the dynamic renderer) executing near the user — both visible separately in Vercel deployment analytics (samcheek.com, 2026-03-25). Vercel globally purges CDN caches across all regions within 300 milliseconds of revalidation; shells persist until explicitly revalidated (vercel.com/docs/partial-prerendering, last updated 2026-08-28).

Not the same as browser Speculation Rules prerender. "Prerendering" appears in both the Next.js PPR marketing and in Chrome's Speculation Rules API vocabulary. Shopify's published performance gains (see below) come from browser-level prefetch/prerender via Speculation Rules — the browser prerenders whole pages in a hidden tab. Next.js PPR is a server-side origin-level mechanism. The two are unrelated, often confused. (registry-source, 2026-09-08)

Version history and production status

PPR was first introduced as an experimental feature in Next.js 14 at Next.js Conf 2023 (Vercel, Next.js Conf 25 keynote, 2025-10-24). It iterated through Next.js 15 under the experimental.ppr flag, with an incremental adoption mode (ppr: 'incremental') enabling per-route opt-in via export const experimental_ppr = true. The Next.js 15 docs (as of August 2025) explicitly state the feature is "currently experimental and subject to change, it's not recommended for production."

PPR production readiness in Next.js 15: The official Next.js 15 documentation (nextjs.org, version 15.5.25, 2025-08-05) explicitly states PPR is "currently experimental and subject to change, it's not recommended for production." Multiple 2026 practitioner articles (samcheek.com 2026-03-25; pkgpulse.com 2026-03-16) describe the incremental PPR mode as "production-stable in Next.js 15" and PPR as "default in Next.js 16." The official docs may lag behind canary/RC builds or the practitioners are extrapolating.

Next.js 16 (October 21, 2025) shipped PPR as stable via the Cache Components API (nextjs.org/blog/next-16, 2025-10-21). The experimental.ppr flag and the per-route export const experimental_ppr export were both removed; PPR is now enabled with cacheComponents: true in next.config.js, replacing the previous experimental.dynamicIO flag. The use cache directive allows opt-in annotations on pages, layouts, and individual components (nextjs.org/blog/next-16, 2025-10-21; verified by Vercel Next.js Conf 25 keynote, 2025-10-24).

PPR as a discrete strategy vs. a composition layer: Some sources describe PPR as "the fourth rendering strategy alongside SSG, SSR, and ISR." pkgpulse.com (2026-03-16) and samcheek.com (2026-03-25) explicitly state PPR is not a replacement for ISR — it builds on top of it and all three strategies can co-exist in a single route.

Platform support beyond Vercel: Vercel's Build Adapters API was updated 2026-05-19 to document PPR support on third-party hosting platforms (nextjs.org/docs/app/guides/ppr-platform-guide, 2026-05-19).

Deploy speed: Vercel deploy times for apps with many ISR or PPR pages improved by up to 33% in August 2026, via a change ensuring routing metadata ships in a single upload regardless of size; requires no configuration change (as-of 2026-08-04).

Ecommerce application

Product detail pages — the canonical use case

Ecommerce product detail pages are the primary PPR use case. The recommended split, documented by multiple practitioner and vendor sources:

  • Static shell: product title, hero image, description, specifications, breadcrumbs, schema.org markup (samcheek.com, 2026-03-25; Vercel/BigCommerce at Vercel Ship 2025, 2025-08-04; Mastercard Dynamic Yield pattern)
  • Dynamic Suspense holes: geo-dependent price, inventory stock badge, Add-to-Cart widget state, session-aware recommendations

BigCommerce refactored its open-source Catalyst storefront's data fetching to "make maximum use of Partial Prerendering in Next.js v15, bringing an excellent balance of static page performance with the ability to stream in dynamic elements" — demonstrated at Vercel Ship 2025 by BigCommerce Manager of Developer Relations James Quick (Vercel / BigCommerce, 2025-08-04).

Mastercard Dynamic Yield documented a production PPR pattern where Next.js serves product detail page content first, then streams the shopping cart from the commerce system and personalised recommendations from Dynamic Yield's API as separate Suspense boundaries (dy.dev, undated).

Search results pages where searchParams (sort order, filter state, page number) drives the entire above-fold layout are not suited to PPR: the static shell would be a skeleton with no meaningful content, making full SSR with edge caching or ISR with client-side filtering superior (samcheek.com, 2026-03-25).

The searchParams migration trap

searchParams is the most common PPR migration pitfall. Any page component that destructures searchParams directly from props forces the entire page into dynamic rendering, bypassing PPR. The fix is to move searchParams consumption into a Suspense-wrapped child component so it does not contaminate the shell (samcheek.com, 2026-03-25).

CLS risk

Cumulative Layout Shift (CLS) is the Core Web Vitals|Core Web Vital most at risk from PPR adoption. Suspense fallback components must have explicit fixed dimensions matching the real content dimensions; poorly designed fallbacks that are replaced by larger blocks produce CLS > 0.1 (the "poor" threshold) (samcheek.com, 2026-03-25).

Performance benchmarks (as-of 2026-03-25)

MetricFull SSR (p75)PPR (p75)Improvement
TTFB (Vercel, Shopify Storefront API, 50–200ms API latency)300–800ms20–80ms4–10×
LCP (mobile, PDP with hero image in static shell)1.8–2.4s0.6–1.2s~3×

Source: samcheek.com, 2026-03-25 (single practitioner, methodology not independently verified).

Vercel's own rendering strategy guide (2024-07-23, pre-2026 — stale risk) identified ISR as the recommended strategy for ecommerce product pages and PPR as "the future upgrade path once it stabilises"; with Next.js 16 now stable, this framing is superseded.

Shopify context

Shopify Hydrogen (built on React Router v7, deployed on Oxygen/Cloudflare Workers) currently has no PPR or ISR equivalent. Every Hydrogen route is either edge-rendered dynamically on Oxygen or served from Cloudflare CDN cache; there is no build-time static shell + streaming dynamic holes mechanism (naturaily.com, 2025-10-28).

Shopify's published performance improvements come from browser Speculation Rules, not from PPR. Shopify rolled out Speculation Rules platform-wide in late June 2025: average improvements of 130ms desktop and 180ms mobile across TTFB, FCP, and LCP (performance.shopify.com, undated — accessed via fudge.ai, 2026-08-09). Moving the ruleset eagerness from conservative to moderate produced median desktop gains of 285ms TTFB, 224ms FCP, and 228ms LCP, with a 14% increase in total HTML requests from supporting browsers (performance.shopify.com, undated).

Framework comparison

PPR is Next.js-only. Astro, SvelteKit, and Remix have no equivalent mechanism. Astro's Island architecture is philosophically similar — static HTML shell with interactive client-side islands — but delivers client-side JavaScript interactivity, not server-streamed dynamic HTML (pkgpulse.com, 2026-03-16).

Security

A May 2026 coordinated security release (Next.js 15.5.18 and 16.2.6) addressed 13 advisories including a High-severity denial-of-service vulnerability via connection exhaustion specifically affecting applications using Cache Components (PPR), requiring immediate upgrade (vercel.com/changelog/next-js-may-2026-security-release, 2026-05-07).

CVE-2025-59472 is a separate DoS vulnerability in Next.js PPR minimal mode: the resume endpoint accepted unauthenticated POST requests and buffered the body with Buffer.concat() with no size cap, enabling memory exhaustion; fixed in Next.js 15.6.0-canary.61 and 16.1.5 (miggo.io CVE database, undated).

Key terms

TermMeaning
Static shellThe build-time pre-rendered HTML document, cached at CDN edge — includes <head>, metadata, LCP image preload hints
Suspense boundaryA <Suspense> React wrapper that marks dynamic content and receives streamed HTML at request time
Dynamic holeThe placeholder in the static shell that is replaced by streamed dynamic content
Cache ComponentsNext.js 16 API that made PPR stable — use cache directive + cacheComponents: true config
Full Route CacheNext.js mechanism for caching complete route renders; PPR restores this for routes previously broken by dynamic signals inside Suspense
Speculation RulesChrome's client-side prerendering API (browser prerenders pages in a hidden tab) — unrelated to Next.js PPR, but frequently confused with it
Research agent · 2026-09-08