Skip to the solution
HardFrontend8 min read

What is Partial Prerendering (PPR) in Next.js?

795 views

The problem

Question presented to candidate: "Our product page is static except for the cart count and a personal greeting, so the whole route renders per request. How would Partial Prerendering change that, and how do you turn it on in Next.js 16?"

What a strong answer should cover:

  • PPR prerenders a static shell of a route at build time and leaves holes for request-time content, marked by Suspense boundaries.
  • At request time the shell and the fallbacks are sent immediately, and the dynamic parts stream into the same response.
  • In Next.js 16 it is part of Cache Components: enable cacheComponents: true (since 16.4 together with partialPrefetching, which new create-next-app projects already set); the old experimental.ppr flag now fails the build.
  • Request-time APIs such as cookies() must sit inside Suspense (or be cached with 'use cache'), otherwise the build reports blocking data.
  • Route segment config like dynamic and revalidate is not compatible with cacheComponents.

Clarifying questions expected:

  • "Which parts are personalised or need request data?" β€” those become Suspense holes.
  • "Are you on Next.js 16?" β€” the configuration differs from the 15 canary.

Code / implementation expected: Yes β€” the config flag and a page with one dynamic hole.

  • nextjs
  • ppr
  • rendering
  • performance

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 8 sections

Read the code

Enabling PPR and a page with one dynamic hole
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = { cacheComponents: true, partialPrefetching: true }; // both are set by create-next-app since 16.4
export default nextConfig;

// app/product/page.tsx
import { Suspense } from "react";
import { cookies } from "next/headers";

async function Greeting() {
  const user = (await cookies()).get("user")?.value ?? "guest";
  return <p>Welcome back, {user}</p>;
}

export default function ProductPage() {
  return (
    <main>
      <h1>Trail Runner 2</h1>                         {/* part of the static shell */}
      <Suspense fallback={<p>Loading your greeting...</p>}>
        <Greeting />                                   {/* rendered per request */}
      </Suspense>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 108 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextHard

What are parallel routes (@slot) in Next.js and when would you use them?

Continue