Next.js Discord

Discord Forum

How to correctly cache GET routes?

Unanswered
Russo-European Laika posted this in #help-forum
Open in Discord
Russo-European LaikaOP
I pushed the code below to prod, but it seems that it caches forever. I would wait 2 mins, 5 mins, 10 mins, etc. and the same response was always returned and displayed on web pages. The data was also confirmed to have changed within those time frames.

28 Replies

Russo-European LaikaOP
My goal is to cache the response of this route for 90 seconds. I've tried adding custom Cache-Control headers, as well as next.revalidate to the fetch() req. Thanks for any help 🙂
@Russo-European Laika I pushed the code below to prod, but it seems that it caches forever. I would wait 2 mins, 5 mins, 10 mins, etc. and the same response was always returned and displayed on web pages. The data was also confirmed to have changed within those time frames.
Turkish Van
I might be wrong, but Your Route Handler shouldn't be even cached, by default, at all. You are using the Request object with the GET method which automatically results into opting out of caching.

Take a look here: https://nextjs.org/docs/app/building-your-application/routing/route-handlers#opting-out-of-caching

Are You sure You are not trying to cache it at place of it being called?

For example, there might be a function that You use to request data from that Router Handler which is being cached.
It might be helpful if You provided us with code snippet of You trying to request data from it inside of the component.
@Russo-European Laika Thanks, I will look into it further. I thought you could cache routes the same as caching pages.
Turkish Van
You absolutely can! GET Route Handler are cached by default. Take a look at link provided above in case You would like to dive a bit deeper into it.

But there are some edge cases which result into it opting out of cache.
Russo-European LaikaOP
Does the page need force-dynamic at the top?
And then I can cache the routes as needed?
@Russo-European Laika Click to see attachment
Turkish Van
Could You provide the code of the either getClan or getRace function, the one that requests data from the Route Handler provided above?
Russo-European LaikaOP
Just a simple service call, both are nearly identical
I guess I'm just confused as to where the caching should be added. Should next.revalidate be in this fetch()?
@Russo-European Laika Click to see attachment
Turkish Van
Is there a part where You are trying to generate static params for that page by using the generateStaticParams function?

Try adding export const revalidate = 90 at the top of the component, above ClanRace component.
@Turkish Van Is there a part where You are trying to generate static params for that page by using the `generateStaticParams` function? Try adding `export const revalidate = 90` at the top of the component, above `ClanRace` component.
Russo-European LaikaOP
using the generateStaticParams function?
No, I don't use that at all.

My goal was to cache the getClan route for 90 secs, and getRace for 30 secs. If I add revalidate = 90 to the top of the page, would that just cache all requests (the entire page) for 90 secs?
getClan and getRace are used in other parts of my app, that's why
@Russo-European Laika > using the generateStaticParams function? No, I don't use that at all. My goal was to cache the `getClan` route for 90 secs, and `getRace` for 30 secs. If I add `revalidate = 90` to the top of the page, would that just cache all requests (the entire page) for 90 secs?
Turkish Van
Oh, You could try adding these options to Your fetch fetch('https://...', { next: { revalidate: 3600 } }).

It might look like this:
export async function getRace(tag, getRaceStats = false) {
  return fetch(`${HOST}/api/clan/race?tag=${formatTag(tag)}&getRaceStats=${getRaceStats}`, { next: { revalidate: 90 } }).then(res => res.json());
}


Take a look here: https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#time-based-revalidation
Russo-European LaikaOP
Thanks. Out of curiosity, what makes this different than what I had originally?
Where I added it to the top of the GET route
Thanks for your help btw 🙂
@Russo-European Laika Thanks. Out of curiosity, what makes this different than what I had originally?
Turkish Van
So the following explanation is based on my understanding, and since all of this is pretty new, I might be wrong.

Let's say You had a function getRandomNumber that gives You a random number each time You call it and is NEVER being cached.

Then, let's say You also had a function getRandomNumberCached that calls the getRandomNumber function and retrieves the number back to You. But, the getRandomNumberCached function IS cached.

So the result of it would be:
- First call:
You call getRandomNumberCached -> There is no cache -> it gets executed -> it calls a getRandomNumber function -> it receives the number, stores it in the cache and it gets back to You
- Second call:
You call getRandomNumberCached -> There is a cache -> it reads the cached value -> it returns the cached value to You
- Third call:
The same thing happens again.

So, the function getRandomNumberCached would retrieve the cached value as long as it does not get revalidated.

That is why I assumed there might be a function at the higher level that is caching the value which results in behaviour You are facing.
I got it working now. One more quick question, is it possible to use both:
{
   next: {
      revalidate: 90,
      tags: [`clan-${tag}`]
   }
}
My end goal is to cache the data for 90 seconds, but there is 1 scenario where the data needs to be up to date on request. I was trying to use revalidateTag right before making that request, but doesn't seem to do it. Maybe I'm misunderstanding something
Same issue with revalidatePath. Maybe it's because the GET req has search params?
Russo-European LaikaOP
My end goal would be something like this. Is this not possible?
@Russo-European Laika I got it working now. One more quick question, is it possible to use both: js { next: { revalidate: 90, tags: [`clan-${tag}`] } }
Turkish Van
Yes, this should be possible.

Could You provide the code snippet of the function where the revalidateTag function is being used?
@Russo-European Laika My end goal would be something like this. Is this not possible?
Turkish Van
I might be wrong but, this wouldn't work since revalidatePath function expects a page/layout path and not the api route path.

It would work in case You passed to it the path to the page where the getClan function is being used, that would revalidate the data retrieved by that function. But, since You said that those functions are being used in multiple places across the app, that might not be the best solution.