import Link from 'next/link'; import { Suspense } from 'react'; import { cacheLife, cacheTag, revalidateTag } from 'next/cache'; function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } async function getSlowTaggedValue() { 'use cache'; // Keep this short so you can observe SWR behavior quickly. // stale: after 2s the entry is considered stale // revalidate: after 8s Next may attempt to refresh // expire: after 60s it must be recomputed cacheLife({ stale: 2, revalidate: 8, expire: 60 }); cacheTag('cache-lab:swr'); // Make regeneration visibly expensive so you can tell whether the request was // served from stale cache (fast) or blocked on recomputation (slow). await sleep(3000); return { computedAt: Date.now(), value: Math.random(), note: 'This function always sleeps ~3s when it actually executes.', }; } async function triggerRevalidateTag() { 'use server'; revalidateTag('cache-lab:swr', { expire: 1 }); } async function CachedPanel() { const data = await getSlowTaggedValue(); return (
computedAt:{' '} {data.computedAt}
value:{' '} {data.value}
{data.note}
); } export default function StaleWhileRevalidatePage() { return (
← Back to Cache Lab

SWR: stale-while-revalidate (slow)

This page is designed to make stale-while-revalidate behavior visible. The cached function sleeps ~3 seconds whenever it really runs.

Loading cached content… (first time can take ~3s) } >

How to observe SWR (non-blocking)

1) Load this page once (expect ~3s on the very first load).

2) Wait ~3 seconds so the entry becomes stale{' '} (stale=2s).

3) Click revalidateTag.

4) Immediately reload the page:

If SWR is working, the reload should be fast and you may still see the old computedAt/value (stale served).
Reload again after ~3-4 seconds and you should see a new computedAt/value.
If SWR is not working, the reload will block for ~3 seconds.
cacheLife: {'{ stale: 2, revalidate: 8, expire: 60 }'}
); }