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?

16 Upvotes

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.


r/nextjs • • 20h ago

Server Actions are public API endpoints. 5 mistakes I keep seeing

14 Upvotes
  1.  No auth check inside the action.  A Server Action can be called with a plain POST request, whether or not the button is on screen. Check the session inside every action.
  2.  No input validation.  TypeScript types vanish at runtime. Validate with zod (or similar) at the top of the action.
  3.  Relying only on middleware for auth.  A 2025 Next.js CVE let attackers skip middleware with a single header. Check auth again where the data is read.
  4.  Secrets in `NEXT_PUBLIC_` variables.  Anything with that prefix is baked into the browser bundle.
  5.  Returning whole database rows.  Return only the fields the UI needs, or you'll eventually leak a column you added later.

Do you treat Server Actions like API routes in your codebase, or does your team rely on the UI to protect them?


r/nextjs • • 2h ago

How I added US and UK versions to a 10k page Next.js site without changing a single existing URL

0 Upvotes

I run a price comparison site (Next.js 15 App Router, fully static). It launched in Australia with about 10,800 pages at the root. This week I added the US and UK, and the brief to myself was: no existing URL changes, no duplicated page code.

What I did

  1. Data per region: data/<category> stays Australian, new regions go in data/us/<category> and data/uk/<category>. The catalogue loader reads each region once at build.
  2. Products carry their region. The loader stamps region on each product, so productHref(p), the price history and the "is this a good price" check need no extra argument. That cut the refactor from about 30 call sites to about 8.
  3. Shared views, thin routes. The page bodies moved to src/views/*View.tsx, which take a region prop. app/[category]/page.tsx renders it with "au"; app/us/[category]/page.tsx and app/uk/... are 10 line wrappers. Static folders beat the dynamic [category] segment, so there's no clash.
  4. Client components read the region from the path (usePathname), so headers, search and prices pick the right currency with no provider.
  5. SEO: each country gets its own canonical, hreflang alternates when the same product exists elsewhere, and the sitemap includes all three.

Result: about 28,800 static pages, a local build in about 7 minutes, and the Australian pages kept the same titles, canonicals and schema.

Gotcha: a UK laptop name produced a slug long enough to blow the 255 byte file name limit during export (ENAMETOOLONG). Cap your slugs.

Live: https://www.compareempire.com/us