SSR — fully dynamic

Every panel below resolves at request time. The probe reads an upstream that returns a different integer on every call, so you do not have to trust the timestamps.

Note what is still static: the heading, this copy, the nav, and every Suspense fallback. Even a page with nothing cached ships a prerendered shell.

What to check

Reload. Every stamp, execution id and probe value changes — every time, with no exceptions.

Then confirm it from outside the browser: for i in 1 2 3; do curl -s localhost:3000/ssr | grep -o 'data-exec="[^"]*"' | md5; done — three different digests.

In next dev the probe may look cached anyway: dev keeps a fetch cache across HMR. Test this one in a build, or set serverComponentsHmrCache: false.

Per-request values

Each of these calls connection() first. Remove that call and the build fails with blocking-prerender-current-time, naming the component — Cache Components will not let a request-time value be silently baked into static HTML.

Request stamp

suspense fallback

streaming at request time — this is what ships in the static shell

Live probe

suspense fallback

streaming at request time — this is what ships in the static shell

Uncached upstreams

Market — uncached

suspense fallback

streaming at request time — this is what ships in the static shell

Station — uncached

suspense fallback

streaming at request time — this is what ships in the static shell

Request context

Reading cookies() or headers() no longer opts the whole route into dynamic rendering — it defers only this subtree. That change is the heart of PPR, and /ppr shows it on a page that has cached content around it.

cookies() and headers()

suspense fallback

streaming at request time — this is what ships in the static shell

The client router can serve a cached RSC payload on back/forward navigation. Use a real document request when you want to be sure you hit the server: