---
title: "Next.js: Cache invalidation and freshness"
slug: "nextjs-cache-invalidation"
category: "frontend"
tags: ["frontend", "nextjs", "caching", "revalidate", "router-cache", "dynamic-rendering"]
status: "stable"
last_updated: 2026-09-27
summary: "How to make cached Next.js data go stale on purpose: revalidateTag versus revalidatePath, dynamic functions and route segment config, and tuning the client Router Cache with staleTimes."
related: ["[[frontend/nextjs-caching]]", "[[frontend/nextjs-server-actions]]", "[[frontend/nextjs-async-dynamic-apis]]", "[[frontend/nextjs-app-router]]", "[[frontend/nextjs]]"]
---

## 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 [[frontend/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.

```ts
"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.

```tsx
// 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:

```ts
// 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

- [[frontend/nextjs-caching]]: what gets cached and how to opt in
- [[frontend/nextjs-server-actions]]
- [[frontend/nextjs-async-dynamic-apis]]
- [[frontend/nextjs-app-router]]
- [[frontend/nextjs]]
- [[ops/vercel]]
