cacheLife profiles

Fifteen profiles — seven built in, eight defined in next.config.ts — each caching the same numeric probe. Grouped by what their lifetime does to prerendering rather than by duration.

Four of them (probe-*) exist only to sit on either side of a documented threshold, so you can see the boundary rather than take it on faith.

What to check

Which ones made it into the HTML. After a build, run curl -s localhost:3000/cache-life | grep -o 'data-fallback="[^"]*"' | sort -u. It lists exactly the profiles that could not be prerendered, and it should be the first group and nothing else.

Which ones move. Reload every few seconds. The short-window profiles change value on their own schedule; max and weeks never will.

The enforcement. Move any panel out of the first group and into a group without a Suspense boundary, then build. It fails and names the component.

App Shell. The difference between the last two groups only shows up in prefetching — see /prefetch for how to observe it in the network tab.

The profiles

profilestalerevalidateexpireprerender
default5m15mneverprerendered-shellFramework default when no cacheLife is called.
seconds30s1s1mdynamic-holeThe only preset that falls below a threshold — its 1min expire keeps it out of prerenders.
minutes5m1m1hprerendered-shellFrequently updated content.
hours5m1h1dprerendered-shellSeveral updates a day.
days5m1d7dprerendered-shellDaily updates.
weeks5m7d30dprerendered-shellWeekly updates.
max5m30d365dprerendered-shellEffectively permanent. What you want for immutable upstreams.
short(custom)30s1m5mprerendered-no-shellPre-existing project profile. Sits right on the expire boundary at exactly 300s.
blog(custom)1m5m1hprerendered-no-shellPre-existing project profile. Prerendered, but excluded from the App Shell.
isr-15(custom)30s15s10mprerendered-no-shellFast ISR window — background regeneration is observable in about 15 seconds.
isr-60(custom)30s1m30mprerendered-no-shellOne minute ISR window, for comparison against isr-15.
probe-no-prerender-stale(custom)10s1m10mdynamic-holestale below 30s — excluded from prerenders, so it becomes a dynamic hole.
probe-no-prerender-expire(custom)30s20s2mdynamic-holeexpire below 5min — also excluded from prerenders.
probe-no-shell(custom)1m2m15mprerendered-no-shellstale between 30s and 5min — prerendered, but kept out of the App Shell.
probe-shell(custom)10m2m1hprerendered-shellstale at or above 5min — prerendered and App Shell eligible.

stale is a client-router concern: how long the browser reuses cached content without asking the server. revalidate is when the server starts regenerating in the background. expire is the point past which a request has to wait. Only stale and expire affect prerendering.

Dynamic holes — dynamic hole — resolved at request time

Cached, but too short-lived to prerender, so these resolve at request time behind a <Suspense> boundary. They are still shared cache entries — two visitors within the window get the same number — they just are not in the static HTML.

seconds

suspense fallback

The only preset that falls below a threshold — its 1min expire keeps it out of prerenders.

probe-no-prerender-stale

suspense fallback

stale below 30s — excluded from prerenders, so it becomes a dynamic hole.

probe-no-prerender-expire

suspense fallback

expire below 5min — also excluded from prerenders.

Prerendered, not App Shell eligible — prerendered, excluded from App Shell

In the static HTML for a direct visit, but excluded from the reusable per-route App Shell that partialPrefetching prefetches. No Suspense boundary needed.

short

use cache
cacheLife
short
upstream
411ms

ran at exec 13ls50age …

probe 646,056

30s stale · 1m revalidate · 5m expire — Pre-existing project profile. Sits right on the expire boundary at exactly 300s.

blog

use cache
cacheLife
blog
upstream
419ms

ran at exec 96j5jyage …

probe 941,308

1m stale · 5m revalidate · 1h expire — Pre-existing project profile. Prerendered, but excluded from the App Shell.

isr-15

use cache
cacheLife
isr-15
upstream
326ms

ran at exec svaopkage …

probe 236,059

30s stale · 15s revalidate · 10m expire — Fast ISR window — background regeneration is observable in about 15 seconds.

isr-60

use cache
cacheLife
isr-60
upstream
404ms

ran at exec gl7d9eage …

probe 503,521

30s stale · 1m revalidate · 30m expire — One minute ISR window, for comparison against isr-15.

probe-no-shell

use cache
cacheLife
probe-no-shell
upstream
525ms

ran at exec fyw1z5age …

probe 81,411

1m stale · 2m revalidate · 15m expire — stale between 30s and 5min — prerendered, but kept out of the App Shell.

Prerendered and App Shell eligible — prerendered and App Shell eligible

The fully static end of the range: in the HTML, and in the prefetched shell.

default

use cache
cacheLife
default
upstream
392ms

ran at exec gl3b24age …

probe 742,136

5m stale · 15m revalidate · never expire — Framework default when no cacheLife is called.

minutes

use cache
cacheLife
minutes
upstream
404ms

ran at exec b295vrage …

probe 524,932

5m stale · 1m revalidate · 1h expire — Frequently updated content.

hours

use cache
cacheLife
hours
upstream
320ms

ran at exec fsxxusage …

probe 704,917

5m stale · 1h revalidate · 1d expire — Several updates a day.

days

use cache
cacheLife
days
upstream
378ms

ran at exec y7xhqbage …

probe 912,481

5m stale · 1d revalidate · 7d expire — Daily updates.

weeks

use cache
cacheLife
weeks
upstream
527ms

ran at exec c4prftage …

probe 624,869

5m stale · 7d revalidate · 30d expire — Weekly updates.

max

use cache
cacheLife
max
upstream
374ms

ran at exec tyru5kage …

probe 60,253

5m stale · 30d revalidate · 365d expire — Effectively permanent. What you want for immutable upstreams.

probe-shell

use cache
cacheLife
probe-shell
upstream
395ms

ran at exec ju9u95age …

probe 472,730

10m stale · 2m revalidate · 1h expire — stale at or above 5min — prerendered and App Shell eligible.