Overview
Caching in Next.js is only safe when every cached resource has a known way to become fresh again. This page covers the invalidation and freshness controls: tag and path revalidation from server actions, the dynamic functions that opt a route out of static rendering, route segment config that forces one mode or the other, and the client-side Router Cache budget. What gets cached in the first place ("use cache", the four-layer model, fetch options, unstable_cache) lives in nextjs-caching.
Invalidate by tag for collections, by path for pages
revalidateTag("posts") invalidates every cache entry tagged "posts", across every route. revalidatePath("/posts/[slug]", "page") invalidates the Full Route Cache and the Router Cache for the matching segment.
"use server";
import { revalidatePath, revalidateTag } from "next/cache";
export async function createPost(formData: FormData) {
await db.post.create({ data: parse(formData) });
revalidateTag("posts"); // any listing, any layout
revalidatePath("/posts"); // the index page
}Tag for collections (a “posts” feed shown in three places). Path for a single page that changed. Mixing is fine; document which strategy each resource uses.
Opt out of caching with dynamic functions
Calling cookies(), headers(), draftMode(), or searchParams inside a server component opts the whole route segment out of static rendering. The Full Route Cache no longer applies; data caching still works fetch-by-fetch.
// This page renders per-request because it reads cookies.
import { cookies } from "next/headers";
export default async function Account() {
const session = await getSession(await cookies());
return <Profile user={session.user} />;
}Force dynamic rendering explicitly with export const dynamic = "force-dynamic". Force static with export const dynamic = "force-static" and the build fails if the route uses dynamic functions. Pick the constraint that matches the route’s data freshness.
Control the Router Cache with staleTimes
The Router Cache holds RSC payloads for routes the user already visited so a back navigation paints from memory. In Next.js 15 the defaults are dynamic: 30 and static: 180 (seconds). The client router additionally enforces a 30s minimum stale time, so setting dynamic: 0 does not fully disable the cache. Tune the budget per project:
// next.config.ts
export default {
experimental: {
staleTimes: { dynamic: 30, static: 180 },
},
};Use a higher dynamic stale time for read-heavy dashboards. For apps where the user expects fresh data after every action, rely on revalidatePath and revalidateTag from server actions rather than a low stale time; they invalidate the matching Router Cache entries directly, which a staleTimes value cannot guarantee given the 30s client minimum.
Related
- nextjs-caching: what gets cached and how to opt in
- nextjs-server-actions
- nextjs-async-dynamic-apis
- nextjs-app-router
- nextjs
- vercel