`use cache: private` not working during client-side navigation
Link to the code that reproduces this issue
https://github.com/ajaykarthikr/next-16-use-cache-private-bug
To Reproduce
-
Create a cached function with "use cache: private" that uses cookies():
// lib/user.ts import { cookies } from "next/headers"; import { cacheTag, cacheLife } from "next/cache"; export async function getUser() { "use cache: private"; cacheTag(`userdata`); cacheLife({ stale: 30 }); const sessionId = (await cookies()).get('session-id')?.value || 'guest' console.log("Fetching user data"); // This logs on every navigation await new Promise((resolve) => setTimeout(resolve, 5000)); const timestamp = new Date().toISOString(); return { user: { name: "Ajay", email: "[email protected]" }, timestamp: timestamp, } } -
Use this function in a Server Component page:
// app/about/page.tsx import { Suspense } from "react"; import { getUser } from "../../lib/user"; export default async function Page() { return ( <div> <h1>About Page</h1> <Suspense fallback={<p>Loading...</p>}> <Content /> </Suspense> </div> ) } async function Content() { const data = await getUser(); return ( <div> <h1>{data.user.name}</h1> <p>Fetched at: {data.timestamp}</p> </div> ); } -
Configure next.config.ts:
import type { NextConfig } from "next"; const nextConfig: NextConfig = { cacheComponents: true, }; export default nextConfig; -
Navigate to the page (e.g., /about), then navigate away, then navigate back using client-side navigation (using <Link> component)
Current vs. Expected behavior
Expected: The cached function should return the cached result during the 30-second stale period, showing the same timestamp and not logging "Fetching user data" on subsequent navigations.
Actual: The function re-executes on every client-side navigation, showing a new timestamp each time and logging "Fetching user data" in the console.
Demo: https://next-16-use-cache-private-bug.vercel.app/
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.0.0: Wed Sep 17 21:42:08 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T8132
Available memory (MB): 24576
Available CPU cores: 10
Binaries:
Node: 22.20.0
npm: 10.9.3
Yarn: N/A
pnpm: N/A
Relevant Packages:
next: 16.0.2-canary.3 // Latest available version is detected (16.0.2-canary.3).
eslint-config-next: N/A
react: 19.2.0
react-dom: 19.2.0
typescript: 5.9.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Use Cache
Which stage(s) are affected? (Select all that apply)
next start (local), Vercel (Deployed)
Additional context
- The "use cache: private" directive is supposed to work with cookies() API according to the documentation
- This appears to be related to Router Cache interaction with function-level caching during client-side navigation
- The 2-second artificial delay in the reproduction makes it easy to observe when the function re-executes
Hey @ajaykarthikr , This looks interesting, I'd love to take a closer look and work on a fix or reproduction enhancement. Could you please assign this issue to me if possible? Thanks for the clear repro steps
Im also having a very similar issue, just to add onto this, when running in dev, the whole page hangs until the component that uses private cache has finished rendering. When running a build the component is streamed in but the result never cached.
The same reason brought me here. The behaviour isn't what's documented. I had to include the old next: {revalidate} to get caching
I wish the docs were clearer, but nothing is cached client side unless it's prefetched. (Unless you alter experimental.staleTimes.dynamic to be non-zero)
By default anything static or marked 'use cache' is prerendered and prefetched. But not 'use cache: private'. So we need to set prefetch={true} on link (as opposed to 'auto'/null), or call router.prefetch.
I think the plan is that in future we can configure 'runtime prefetching' for a page, which means that content marked 'use cache: private' will also be prefetched and cached by default. But that's not yet documented/recommended.
It also doesn't work. I used "use cache: private" for queries with searchParams, but I can see from the server logs that the identical query is repeated, creating a new request to the server each time. If you use "use cache", then everything is ok, queries are cached and not duplicated.
However, according to the documentation, you should use "use cache: private" if you're using searchParams.
I don’t use Next.js API routes. All API requests go to an external Fastify backend.
I encountered the same problem; "use cache:private" doesn't work at all.
I have this same issue. use cache: private doesn't work at all for men and like someone mentioned as well, it increased loadtimes a lot.
I have this same issue. use cache: private doesn't work at all for men and like someone mentioned as well, it increased loadtimes a lot.
Use next: { revalidate: 3600 } temporarily until they fix it.
It's strange that such a critical bug hasn't been fixed yet.
same here.
@aprinciple Do you mean put next: { revalidate: 3600 } in "next.config.ts"?
same here.
@aprinciple Do you mean put
next: { revalidate: 3600 }in "next.config.ts"?
No, you have to specify this in the server request, for example.
export default async function Page() {
const data = await fetch('https://...', { next: { revalidate: 3600 } })
}
I had the same issue, but now I moved with "use catch" passing the user ID as props so each cache will be used by its own user.
I think it's just better to use the old caching system (next: {}) instead of this. use cache wasn't designed for dynamism so it may have an unknown effect especially security wise in production.
I had the same issue, but now I moved with "use catch" passing the user ID as props so each cache will be used by its own user.