cacheLife profiles
Fifteen profiles, seven built in and eight defined in next.config.ts, each caching the same numeric probe. They are grouped by what their lifetime does to prerendering, not by duration.
The four probe-* profiles sit on either side of a documented threshold, so you can see each boundary for yourself.
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 the profiles that could not be prerendered. That 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. /prefetch shows how to see it in the network tab.
The profiles
| profile | stale | revalidate | expire | prerender |
|---|---|---|---|---|
| default | 5m | 15m | never | prerendered-shellFramework default when no cacheLife is called. |
| seconds | 30s | 1s | 1m | dynamic-holeThe only preset below a threshold. Its 1min expire keeps it out of prerenders. |
| minutes | 5m | 1m | 1h | prerendered-shellFrequently updated content. |
| hours | 5m | 1h | 1d | prerendered-shellSeveral updates a day. |
| days | 5m | 1d | 7d | prerendered-shellDaily updates. |
| weeks | 5m | 7d | 30d | prerendered-shellWeekly updates. |
| max | 5m | 30d | 365d | prerendered-shellEffectively permanent. Use it for upstreams that never change. |
| short(custom) | 30s | 1m | 5m | prerendered-no-shellExisting project profile. Its 300s expire is exactly on the 5min boundary, so it is still prerendered. |
| blog(custom) | 1m | 5m | 1h | prerendered-no-shellExisting project profile. Prerendered, but excluded from the App Shell. |
| isr-15(custom) | 30s | 15s | 10m | prerendered-no-shellFast ISR window. Background regeneration shows up after about 15 seconds. |
| isr-60(custom) | 30s | 1m | 30m | prerendered-no-shellOne minute ISR window, for comparison against isr-15. |
| probe-no-prerender-stale(custom) | 10s | 1m | 10m | dynamic-holestale below 30s, so it is excluded from prerenders and becomes a dynamic hole. |
| probe-no-prerender-expire(custom) | 30s | 20s | 2m | dynamic-holeexpire below 5min, so it is also excluded from prerenders. |
| probe-no-shell(custom) | 1m | 2m | 15m | prerendered-no-shellstale between 30s and 5min, so it is prerendered but kept out of the App Shell. |
| probe-shell(custom) | 10m | 2m | 1h | prerendered-shellstale at or above 5min, so it is 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
<Suspense> boundary. They are still shared cache entries, so two visitors within the window get the same number. They are just not in the static HTML.seconds
suspense fallbackThe only preset below a threshold. Its 1min expire keeps it out of prerenders.
probe-no-prerender-stale
suspense fallbackstale below 30s, so it is excluded from prerenders and becomes a dynamic hole.
probe-no-prerender-expire
suspense fallbackexpire below 5min, so it is also excluded from prerenders.
Prerendered, not App Shell eligible: prerendered, excluded from App Shell
partialPrefetching prefetches. No Suspense boundary needed.short
use cache- cacheLife
- short
- upstream
- 335ms
ran at exec h35dq3age …
probe 226,818
30s stale · 1m revalidate · 5m expire. Existing project profile. Its 300s expire is exactly on the 5min boundary, so it is still prerendered.
blog
use cache- cacheLife
- blog
- upstream
- 288ms
ran at exec dsvinnage …
probe 515,051
1m stale · 5m revalidate · 1h expire. Existing project profile. Prerendered, but excluded from the App Shell.
isr-15
use cache- cacheLife
- isr-15
- upstream
- 448ms
ran at exec oc7icsage …
probe 771,042
30s stale · 15s revalidate · 10m expire. Fast ISR window. Background regeneration shows up after about 15 seconds.
isr-60
use cache- cacheLife
- isr-60
- upstream
- 266ms
ran at exec 5xgenjage …
probe 581,256
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
- 282ms
ran at exec 48u6ifage …
probe 344,998
1m stale · 2m revalidate · 15m expire. stale between 30s and 5min, so it is prerendered but kept out of the App Shell.
Prerendered and App Shell eligible: prerendered and App Shell eligible
default
use cache- cacheLife
- default
- upstream
- 279ms
ran at exec ou2yskage …
probe 35,207
5m stale · 15m revalidate · never expire. Framework default when no cacheLife is called.
minutes
use cache- cacheLife
- minutes
- upstream
- 363ms
ran at exec nleu2oage …
probe 979,077
5m stale · 1m revalidate · 1h expire. Frequently updated content.
hours
use cache- cacheLife
- hours
- upstream
- 385ms
ran at exec hn3jq4age …
probe 240,654
5m stale · 1h revalidate · 1d expire. Several updates a day.
days
use cache- cacheLife
- days
- upstream
- 345ms
ran at exec 830ul4age …
probe 529,833
5m stale · 1d revalidate · 7d expire. Daily updates.
weeks
use cache- cacheLife
- weeks
- upstream
- 365ms
ran at exec 6yxwq8age …
probe 626,847
5m stale · 7d revalidate · 30d expire. Weekly updates.
max
use cache- cacheLife
- max
- upstream
- 351ms
ran at exec za2ep5age …
probe 427,582
5m stale · 30d revalidate · 365d expire. Effectively permanent. Use it for upstreams that never change.
probe-shell
use cache- cacheLife
- probe-shell
- upstream
- 355ms
ran at exec 25p97tage …
probe 909,423
10m stale · 2m revalidate · 1h expire. stale at or above 5min, so it is prerendered and App Shell eligible.