cacheLife blocks navigation and prevents Suspense streaming
Unanswered
Standard Chinchilla posted this in #help-forum
Standard ChinchillaOP
Hey everyone! I'm trying to figure out
I want to cache data for 3 seconds, and here's the behavior I'm going for:
1. First visit: Show my skeleton UI → wait 3 seconds → display data ✨
2. Navigate back within 3 seconds: Show cached data immediately (instant, no loading!)
3. Navigate back after 3 seconds: Cache expired → show skeleton again → fetch fresh data
## The Problem 😅
With
- The page completely blocks/freezes for 3 seconds 😢
- DevTools shows "prerendering" during the block
- My Suspense fallback never shows up
- Users just see a blank page instead of my nice skeleton
With just
- Great news: page doesn't block! 🎉
- Bad news: cache never expires... like, ever
- Even after waiting 30+ seconds, it keeps showing old cached data
- Skeleton never appears again
## Here's my code
## What I've tried so far
Option 1:
→ Page blocks, no streaming 😔
Option 2:
→ No blocking (yay!) but cache never expires (oh no!)
The Suspense boundary works perfectly when I use only "use cache"
Is this the expected behavior? Should
Would really appreciate any pointers or if someone could help me understand what's going on. Thanks in advance! 🙏
cacheLife and running into some confusing behavior. Would really appreciate any insights!I want to cache data for 3 seconds, and here's the behavior I'm going for:
1. First visit: Show my skeleton UI → wait 3 seconds → display data ✨
2. Navigate back within 3 seconds: Show cached data immediately (instant, no loading!)
3. Navigate back after 3 seconds: Cache expired → show skeleton again → fetch fresh data
## The Problem 😅
With
revalidate or expire:- The page completely blocks/freezes for 3 seconds 😢
- DevTools shows "prerendering" during the block
- My Suspense fallback never shows up
- Users just see a blank page instead of my nice skeleton
With just
stale:- Great news: page doesn't block! 🎉
- Bad news: cache never expires... like, ever
- Even after waiting 30+ seconds, it keeps showing old cached data
- Skeleton never appears again
## Here's my code
async function getInsights() {
// I have this 3-second delay on purpose to see my skeleton UI
await new Promise(resolve => setTimeout(resolve, 3000));
return .....
}
export async function Insights() {
return (
<Suspense fallback={<InsightsSkeleton />}>
<InsightsCards />
</Suspense>
);
}
async function InsightsCards() {
'use cache';
cacheLife({ revalidate: 3 }); // This is where things go wrong
const insights = await getInsights();
return <div>{/* render data */}</div>;
}## What I've tried so far
Option 1:
cacheLife({ revalidate: 3 }) or cacheLife({ expire: 3 })→ Page blocks, no streaming 😔
Option 2:
cacheLife({ stale: 3 })→ No blocking (yay!) but cache never expires (oh no!)
The Suspense boundary works perfectly when I use only "use cache"
Is this the expected behavior? Should
revalidate/expire block the page like this?Would really appreciate any pointers or if someone could help me understand what's going on. Thanks in advance! 🙏
1 Reply
Standard ChinchillaOP
Update / Discovery 🔍
I finally figured out what’s happening — the caching behavior is actually different between development and production builds. 🤬
When I run the app in dev mode (pnpm dev), cacheLife({ expire: 3 }) completely blocks rendering and my Suspense fallback never shows up (the same issue I described above).
But when I build the app (pnpm build && pnpm start), everything works perfectly — exactly as expected! The cache revalidates after 3 seconds, the skeleton appears on expired cache, and the page doesn’t freeze.
Honestly, this difference between dev and production feels like one of the worst parts of the Next.js DX right now. It’s the same kind of frustration I’ve hit with Server Actions too — in dev you can throw custom error messages, but in production those messages get swallowed. Having different behaviors between environments makes debugging way harder than it should be 😩
I finally figured out what’s happening — the caching behavior is actually different between development and production builds. 🤬
When I run the app in dev mode (pnpm dev), cacheLife({ expire: 3 }) completely blocks rendering and my Suspense fallback never shows up (the same issue I described above).
But when I build the app (pnpm build && pnpm start), everything works perfectly — exactly as expected! The cache revalidates after 3 seconds, the skeleton appears on expired cache, and the page doesn’t freeze.
Honestly, this difference between dev and production feels like one of the worst parts of the Next.js DX right now. It’s the same kind of frustration I’ve hit with Server Actions too — in dev you can throw custom error messages, but in production those messages get swallowed. Having different behaviors between environments makes debugging way harder than it should be 😩