Is "use cache" actually a trap for large-scale projects (like e-commerce)?
Unanswered
African Slender-snouted Crocodil… posted this in #help-forum
African Slender-snouted CrocodileOP
Hey everyone!
I wanted to open a discussion about Cache Components, but since my post is too long for a single Discord message, I’m breaking it down into a thread below. 🧵
Imagine you’re building a massive e-commerce platform - hundreds of thousands of products, 8 languages, and complex listings with all the filters and pagination you can think of.
I’m deep into something similar right now and SEO is our absolute #1 priority. We need Google to index everything perfectly.
I’ve been exploring Cache Components (Next.js 16), but the more I dig, the more I feel like I'm hitting some serious walls. I'd love to hear how you guys are handling this at scale.
I wanted to open a discussion about Cache Components, but since my post is too long for a single Discord message, I’m breaking it down into a thread below. 🧵
Imagine you’re building a massive e-commerce platform - hundreds of thousands of products, 8 languages, and complex listings with all the filters and pagination you can think of.
I’m deep into something similar right now and SEO is our absolute #1 priority. We need Google to index everything perfectly.
I’ve been exploring Cache Components (Next.js 16), but the more I dig, the more I feel like I'm hitting some serious walls. I'd love to hear how you guys are handling this at scale.
18 Replies
African Slender-snouted CrocodileOP
1. The Suspense vs. SEO dilemma
The "use cache" philosophy relies on wrapping dynamic parts in Suspense. The static shell hits the cache, and the rest streams in. But if Googlebot hits a product page and we're streaming the main content (price, description), isn't it just going to see a skeleton? Since Googlebot’s JS execution is limited, this feels like an SEO disaster.
Plus, for things like user-specific headers or carts, we can already just move those to Client Components. Why use Cache Components and risk the main content not being indexed?
The "use cache" philosophy relies on wrapping dynamic parts in Suspense. The static shell hits the cache, and the rest streams in. But if Googlebot hits a product page and we're streaming the main content (price, description), isn't it just going to see a skeleton? Since Googlebot’s JS execution is limited, this feels like an SEO disaster.
Plus, for things like user-specific headers or carts, we can already just move those to Client Components. Why use Cache Components and risk the main content not being indexed?
2. The generateStaticParams trap & Build Times
Next.js throws an EmptyGenerateStaticParamsError if you return an empty array with Cache Components. Okay, so I’m forced to provide at least some slugs. But here’s the problem: even if I add just a "warmup" batch of products across 8 locales, build times start to skyrocket. It’s just not scalable when you have 100k+ items. You either have a broken build or a 2-hour build.
Next.js throws an EmptyGenerateStaticParamsError if you return an empty array with Cache Components. Okay, so I’m forced to provide at least some slugs. But here’s the problem: even if I add just a "warmup" batch of products across 8 locales, build times start to skyrocket. It’s just not scalable when you have 100k+ items. You either have a broken build or a 2-hour build.
3. The Deployment Factor (Multiple times a day)
We’re deploying new features and fixes several times a day. If every deployment means we have to deal with long build times or potential cache resets, it becomes a nightmare for CI/CD and preview deployments.
How does Cache Components even fit into a high-frequency deployment workflow at this scale?
We’re deploying new features and fixes several times a day. If every deployment means we have to deal with long build times or potential cache resets, it becomes a nightmare for CI/CD and preview deployments.
How does Cache Components even fit into a high-frequency deployment workflow at this scale?
4. Cold cache & Core Web Vitals
That "first hit" on a non-cached page results in a slow TTFB. If that first hit is a real user on Chrome, it tanks our Core Web Vitals (CrUX data). The cache warms up after that, but the damage to our SEO ranking factors is already done.
The Big Question: Why not just stay with traditional fetch?
If I just use:
I get:
- Full SSR (Googlebot sees everything immediately).
- Server-side caching that actually works.
- On-demand invalidation via revalidateTag.
- No build time issues (no need for generateStaticParams).
That "first hit" on a non-cached page results in a slow TTFB. If that first hit is a real user on Chrome, it tanks our Core Web Vitals (CrUX data). The cache warms up after that, but the damage to our SEO ranking factors is already done.
The Big Question: Why not just stay with traditional fetch?
If I just use:
fetch(url, { next: { revalidate: 3600, tags: ['product-id'] } })I get:
- Full SSR (Googlebot sees everything immediately).
- Server-side caching that actually works.
- On-demand invalidation via revalidateTag.
- No build time issues (no need for generateStaticParams).
So, what’s the real benefit of 'use cache' here? Am I missing some revolutionary performance gain that outweighs all these SEO and DX headaches? Or is the "old" fetch-based caching still the better choice for large-scale e-commerce?
Saint Hubert Jura Hound
No need for generateStaticParams
So before you werent actually generating these pages at all. You were still rendering them on demand. Only the data used in them was cached. Thats the difference with cache components, they let you mix dynamic static and cached data.
Now when u tried using generatestaticparams with the cache components yes ur actually generating all those pages during build time which is not viable with any site with hundreds of thousands of pages even without cache components.
U could only build the first x amount of products based on popularity during build and render the rest on demand using generatestaticparams. Those can be cached using cache components
Saint Hubert Jura Hound
This would eliminate the need to render them during build and still give u fast load times as well as lower server load. I think crawlers will struggle with seo at this point unless u include the product data in the static shell by using
https://nextjs.org/docs/app/getting-started/cache-components#how-rendering-works-with-cache-components
use cache on the function returning the product data:https://nextjs.org/docs/app/getting-started/cache-components#how-rendering-works-with-cache-components
As the docs say this is only possible when no request data is needed which i dont see why there would be when building an ecommerce platform
@African Slender-snouted Crocodile **2. The generateStaticParams trap & Build Times**
Next.js throws an EmptyGenerateStaticParamsError if you return an empty array with Cache Components. Okay, so I’m forced to provide at least some slugs. But here’s the problem: even if I add just a "warmup" batch of products across 8 locales, build times start to skyrocket. It’s just not scalable when you have 100k+ items. You either have a broken build or a 2-hour build.
Why broken build? even if only few items are generated, pages can still be statically generated on request time.
@African Slender-snouted Crocodile **3. The Deployment Factor (Multiple times a day)**
We’re deploying new features and fixes several times a day. If every deployment means we have to deal with long build times or potential cache resets, it becomes a nightmare for CI/CD and preview deployments.
How does Cache Components even fit into a high-frequency deployment workflow at this scale?
long build times or potential cache resetsEver tried data caching your data fetches?
CachedComponents is a feature that allows seamless cache syntax than the traditional method of calling functions. It is not one type of cache but an amalgamation of many different cache type working together. The type of cache you might be intereted in is the Data Cache which would cache the output of functions allowing you to have instant result if the parameters or implementation havent changed. This should help if you are implementing new features and multiple deployment as IIRC data caches are persisted across deployments.
@African Slender-snouted Crocodile So, what’s the real benefit of 'use cache' here? Am I missing some revolutionary performance gain that outweighs all these SEO and DX headaches? Or is the "old" fetch-based caching still the better choice for large-scale e-commerce?
So, what’s the real benefit of 'use cache' here?again, use cache are just new syntax to implement caches. it is no different than calling
unstable_cache or fetch or generateStaticParams, and the issue with SEO regarding usage of Suspense still exists pre-"use cache".That being said, you can still able to model everything around "use cache" and have Full SSR, Server-side caching that actually works, revalidateTag (or rather, updateTag)
@alfonsüs ardani > So, what’s the real benefit of 'use cache' here?
again, use cache are just new syntax to implement caches. it is no different than calling `unstable_cache` or `fetch` or `generateStaticParams`, and the issue with SEO regarding usage of Suspense still exists pre-"use cache".
That being said, you can still able to model everything around "use cache" and have Full SSR, Server-side caching that actually works, revalidateTag (or rather, updateTag)
Saint Hubert Jura Hound
Use cache can cache full components or functions which is not the same as the fetch cache or generatestaticparams
https://nextjs.org/docs/app/getting-started/cache-components#how-rendering-works-with-cache-components
https://nextjs.org/docs/app/getting-started/cache-components#how-rendering-works-with-cache-components
Saint Hubert Jura Hound
They operate at different levels of the cache model
https://nextjs.org/docs/app/guides/caching#overview
https://nextjs.org/docs/app/guides/caching#overview
@Saint Hubert Jura Hound Use cache can cache full components or functions which is not the same as the fetch cache or generatestaticparams
https://nextjs.org/docs/app/getting-started/cache-components#how-rendering-works-with-cache-components
Fetch cache and functions that uses "use cache" both uses Data Cache which is stored in .next folder which is persisted betwen deployment.
generateStaticParams are extra function to acomodate static rendering when "use cache" are put on top of the file thereby making the route static.
generateStaticParams are extra function to acomodate static rendering when "use cache" are put on top of the file thereby making the route static.
"use cache" automatically determines which "cache models" to use depending where the directive is used.
@alfonsüs ardani Fetch cache and functions that uses "use cache" both uses Data Cache which is stored in .next folder which is persisted betwen deployment.
generateStaticParams are extra function to acomodate static rendering when "use cache" are put on top of the file thereby making the route static.
Saint Hubert Jura Hound
It was my understanding that by adding the use cache directive to a function when using cache components, nextjs renders the component using the result of the function and adds it to the static shell, which is then stored in the full route cache.
But maybe the result of the function using use cache is still stored in the data cache as well idk.
Either way this would be fundementally different compared to fetch cache when its not used in cache components. Since the result would only be stored in the data cache and used to render incoming requests on demand. Whereas using cache components the entire rendered component can be cached. Is this not the case?
But maybe the result of the function using use cache is still stored in the data cache as well idk.
Either way this would be fundementally different compared to fetch cache when its not used in cache components. Since the result would only be stored in the data cache and used to render incoming requests on demand. Whereas using cache components the entire rendered component can be cached. Is this not the case?
So ur basically trading load on nextjs for bandwidth usage to the cache and load on the cache
Oh hang on sorry i was thinking of remote caching at the end there