Next.js Discord

Discord Forum

Stale-while-revalidate (swr) with the App Router?

Unanswered
Least Storm-Petrel posted this in #help-forum
Open in Discord
Least Storm-PetrelOP
Hi 👋

I've been wondering for a while but never asked:
How can I implement a stale-while-revalidate pattern (like ISR) for pages in the app router?

Meaning, I want to serve static, cached versions of my dynamic page, revalidate it in the background, and have it replaced by the new version if the revalidation is successful.

Is this even possible with the app router?

16 Replies

Least Storm-PetrelOP
Thanks! I didn't see that.
I haven't tried it out yet. But I seem to rember it not working (at least when Next.js 14 was new) when I invalidated a specific tag (i.e. fetch request). Then, all paths immediately switched to SSR on the next request instead of serving a stale version while doing the revalidation in the background.
Is this still the case? Or rather, will it actually do the revalidation always in the background?
American black bear
I am pretty sure it happens in the background but could not find the docs to reference it.
Perhaps someone else sees this and can give you a definitive answer.
Least Storm-PetrelOP
Oh that's intersting. The new docs in the beta show that it probably did behave as a blocking revalidation. The docs now specify for the second arg:

- With profile="max" (recommended): Uses stale-while-revalidate semantics
- Without profile: legacy behavior which is equivalent to updateTag

I find the recommendations non-optimal though:
If I'm cache busting some rarely updated, but computationally expensive and important to be up-to-date data, I do not want the swr behavior.
Meaning, I want to serve static, cached versions of my dynamic page, revalidate it in the background, and have it replaced by the new version if the revalidation is successful.
The latest version of nextjs already does this if you configure your page to have a duration or not using any uncached async api.

You can use "Route segment config" to configure when pages revalidates and it will revalidate in the background while serving stale results.

Im not sure if its possible to do with tags. I havent tested much about static cache recently. But perhaps you can try adding force-cache in the [route segment config](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic)?
@Least Storm-Petrel hey just want to update that its now possible to have SWR like behavior on revalidateTag on Beta version
Least Storm-PetrelOP
if you used duration instead of tag it will do ISR instead of on-demand revalidation
Ah, I see. Thanks. That was not obvious to me.
hey just want to update that its now possible to have SWR like behavior on revalidateTag on Beta version
You mean with profile=max like I mentioned?

Also:
I've just seen that the docs now mention the revalidateTag without a second argument is deprecated, and we should use updateTag. But since we cannot use that in route handlers, an important tool will soon be missing for us. Where can I make my concerns heard?
your concern can be made heard in github discussion/issue ofcourse
have you tried just using revalidateTag in route handlers without profile just as usual?
it is legacy but its not obsolete yet :lolsob:
Least Storm-PetrelOP
Yeah, it's not gone yet, ofc. But it is marked deprecated, and I think that this is a mistake. There is no alternative provided to the depracation that has a similar cache invalidation bahviour for route handlers. E.g. invalidation third party api data using a webhook will get a lot more complicated.

https://github.com/vercel/next.js/discussions/85094