How to Avoid Serving Stale Data on Idle Dynamic Endpoints in Next.js (Built-in Solutions Only)
Answered
Snowshoe posted this in #help-forum
SnowshoeOP
Hey folks! I'm building a Next.js 15 app and want to cache API data but avoid serving stale data when an endpoint doesn't receive traffic for a long time (e.g. 1+ day).
I'm aware of the new use cache directive, but it's still buggy, so I want to stick to built-in stable solutions for now. ( or maybe use the new unstable_cache?)
I’ve looked into:
fetch with next.revalidate → but it serves stale data until someone triggers a revalidation by visiting the route.
A cron job or background ping is hard in my case because I have many dynamic endpoints with unpredictable IDs—so I can’t proactively revalidate them all without knowing which ones are stale.
💡 Goal: I want a way to ensure fresh data is served, even if a dynamic route hasn’t been accessed in a while—using only Next.js built-in tools .
Any tips or creative workarounds?
I'm aware of the new use cache directive, but it's still buggy, so I want to stick to built-in stable solutions for now. ( or maybe use the new unstable_cache?)
I’ve looked into:
fetch with next.revalidate → but it serves stale data until someone triggers a revalidation by visiting the route.
A cron job or background ping is hard in my case because I have many dynamic endpoints with unpredictable IDs—so I can’t proactively revalidate them all without knowing which ones are stale.
💡 Goal: I want a way to ensure fresh data is served, even if a dynamic route hasn’t been accessed in a while—using only Next.js built-in tools .
Any tips or creative workarounds?
Answered by joulev
import { unstable_cache } from "next/cache";
async function getData() {
await new Promise((resolve) => setTimeout(resolve, 1000));
return new Date().toISOString();
}
const revalidate = 10;
function getUniqueKey() {
return Math.floor(new Date().valueOf() / (revalidate * 1000)).toString();
}
async function cachedGetData() {
return unstable_cache(getData, [getUniqueKey()])();
}
export default async function Page() {
const data = await cachedGetData();
return <div>{data}</div>;
}
12 Replies
@Snowshoe Hey folks! I'm building a Next.js 15 app and want to cache API data but avoid serving stale data when an endpoint doesn't receive traffic for a long time (e.g. 1+ day).
I'm aware of the new use cache directive, but it's still buggy, so I want to stick to built-in stable solutions for now. ( or maybe use the new unstable_cache?)
I’ve looked into:
fetch with next.revalidate → but it serves stale data until someone triggers a revalidation by visiting the route.
A cron job or background ping is hard in my case because I have many dynamic endpoints with unpredictable IDs—so I can’t proactively revalidate them all without knowing which ones are stale.
💡 Goal: I want a way to ensure fresh data is served, even if a dynamic route hasn’t been accessed in a while—using only Next.js built-in tools .
Any tips or creative workarounds?
import { unstable_cache } from "next/cache";
async function getData() {
await new Promise((resolve) => setTimeout(resolve, 1000));
return new Date().toISOString();
}
const revalidate = 10;
function getUniqueKey() {
return Math.floor(new Date().valueOf() / (revalidate * 1000)).toString();
}
async function cachedGetData() {
return unstable_cache(getData, [getUniqueKey()])();
}
export default async function Page() {
const data = await cachedGetData();
return <div>{data}</div>;
}
Answer
SnowshoeOP
Wow great idea! Thanks
So basically we do not even need to set the revalidation time since we set it via the key
yeah
SnowshoeOP
How can i delete the stale data from the Data cache? So how can I aviod that the stale cache stays in the vercel Data cache
not possible afaik, nextjs doesn't expose a way to delete old cache
if you need to implement cache deletion, you probably need to write your own cache handler
SnowshoeOP
I do not even see the limit on vercel for the Data cache
SnowshoeOP
FYI => "When the Vercel Data Cache reaches its storage limit, the oldest data is automatically purged based on the Least Recently Used (LRU) " So this solves this by default
oh that's nice
yeah that should automatically delete things for you
SnowshoeOP
Awesome! Thanks for the help