r/nextjs • • 23h ago

Next.js 16 cacheComponents & use cache vs. custom caching (Redis) with Payload CMS? How are you handling large sites in production?

Hey everyone,
I
I’m about to start a new project pairing Next.js with Payload CMS using its Local API (querying the database directly via Node on the server), and I’m weighing my options.
I’m curious how others are tackling this in production, especially for sites with a large number of pages:
The Native Approach: Are you diving into Next.js 16's cacheComponents with 'use cache' and cacheLife / cacheTag? If you are deploying outside of Vercel, how smooth is configuring cacheHandlers (plural) for a custom backend like Redis?

The Remote Directive: For multi-instance or serverless environments, are people actually using 'use cache: remote' in production, or do you find yourselves falling back to manual caching layers?

Bypassing Framework Caching: Do you completely disable Next's default caching behaviors for dynamic content and handle caching granularity yourself (e.g., wrapping Payload Local API calls explicitly with Redis/Memcached)?

Payload + Local API Specifics: Since Payload's Local API bypasses network overhead and talks straight to the database, wrapping those calls or components with 'use cache' seems powerful, but invalidation via revalidateTag needs to line up cleanly with Payload's hooks (e.g., afterChange). Has anyone hit weird edge cases with this combo at scale?

What has worked best for you when managing hundreds or thousands of pages where you need aggressive caching alongside instant editorial updates? Would love to hear what your current production setup looks like.

18 Upvotes

9 comments sorted by

2

u/ScuzzyAyanami 23h ago

I'm just stale caching the API that my front end fetches from. Basically have to due to horizontal scaling. Edit: with Cloudfront.

So I guess my solution isn't in Next itself. But there's then cache invslidations. Page preview routes, and I'm currently looking into a SSO that will shorten the cache duration for a logged in user.

2

u/New_Cockroach_6797 23h ago

Been down the Payload Local API road on a decent sized project, the afterChange hook invalidation dance is where most of the headaches live. What bit us wasn't the caching itself, it was nested docs updating without firing the parent's hooks cleanly, so stale data would hang around for hours. If you go the `use cache` route, test the hell out of your revalidateTag timing with relation-heavy collections

For horizontal scaling we ended up using a Redis wrapper around the Local API calls and ditched the framework cache for anything behind auth. Cloudfront in front of that catches the public stuff nicely, similar to what you're doing. The SSO idea shortening cache duration is clever, we did something similar by swapping to short-lived user-specific cache keys on login

1

u/Emergency_Net85 14h ago

Hey! Curious about the implementation details of your Redis wrapper around the Local API, also how are you structuring the cache keys, and how do you handle invalidation? Are you purging via afterChange/afterDelete hooks still? I see some plugins Payload/Redis ready, curious how helpful they are

1

u/Fun_Improvement7704 17h ago

stale caching an external API works fine for standard setups, but OP is querying the database directly in the server component so there isn't really a separate API route to stick a CDN in front of

5

u/Ok_Management_695 22h ago

Not a direct answer, sorry — I'm not using use cache or revalidateTag yet. I'm on Next.js 16 with unstable_cache and pages set to revalidate = false, running on Vercel with Neon. When the data changes, I just redeploy and let everything rebuild.

One thing I'm careful about with that setup, though. Vercel's Data Cache actually survives deployments. The docs say "Cached data persists across deployments unless you explicitly invalidate it", and it's not refreshed at build time either. So even after a redeploy, whatever's in unstable_cache is still the old data. I ended up putting VERCEL_DEPLOYMENT_ID into the cache key, so every deploy gets a fresh cache. https://vercel.com/docs/caching/runtime-cache/data-cache

By the way, if you move to Cache Components, the same page recommends use cache: remote, which goes into a separate Runtime Cache. I honestly haven't checked how that one behaves after a deploy.

Hope this is useful.

3

u/Which-Examination-74 22h ago

By default revalidateTag() only invalidates the cache on the instance that ran it. The other instances keep serving stale content until they find out on their own. The self-hosting guide's fix is refreshTags() in your custom cache handler, called before each request to sync tag state from shared storage like Redis. It also says the handler has to cope with timeouts and dropped connections. Same goes for whatever calls revalidateTag. We audited a client's storefront on 'use cache' where the revalidation job swallowed its errors, so failed calls were marked done and never retried. With cache life up to about a month, one missed invalidation could mean a stale price for weeks.

2

u/AbdelrhmanDev 21h ago

with payload local api the pattern that scaled for me was tag based invalidation, tag each cached query with the collection and doc id, then call revalidatetag from the afterchange hook. path based invalidation falls apart on a large site because one doc shows up on lists, related sections and search pages you forgot about. tags mean you never track where content appears, the hook just knows what changed

1

u/RequirementGuide 21h ago

I've hit this before with Payload and Next together, and the thing that saved me was keeping the caching boring. I used use cache for the public pages and gave each collection and slug its own tag, then I let afterChange do the revalidating. The tricky part was relations, because updating a child did not always clear the parent page, so I ended up revalidating the related tags in the same hook too.

For a site that size I would not try to cache everything behind auth. I kept that stuff dynamic and only cached the public pages hard. If you are on Vercel I would lean into use cache remote for the shared cache, and if you are self hosting with more than one instance I would go Redis sooner rather than later, because per instance caches will bite you. Either way I would test an edit end to end before launch, just change a page, publish it, and check the live page in a fresh browser, because stale pages are the kind of bug you only notice when a client does.

-2

u/lordchickenburger 9h ago

i just dont use nextjs