The Caching Layers

Next has several caches; the two you touch most are the Data Cache and the Full Route Cache.

Syntaxfetch(url, { next: { tags: ['posts'] } }); revalidateTag('posts');

Next.js caches at multiple levels to make apps fast. You do not manage them all, but it helps to know the main ones:

  • Data Cache — stores fetch results on the server across requests. Controlled by cache and revalidate.
  • Full Route Cache — stores the rendered HTML of static routes at build time.
  • Router Cache — a short-lived client cache of visited routes for instant back/forward navigation.

You invalidate the server caches on demand with revalidatePath and revalidateTag.

Example

Example · typescript
// Tag a fetch, then invalidate it later from a Server Action
const res = await fetch('https://api.example.com/posts', {
  next: { tags: ['posts'] },
});

// elsewhere, after creating a post:
import { revalidateTag } from 'next/cache';
revalidateTag('posts'); // clears every fetch tagged 'posts'

When to use it

  • A developer uses revalidateTag to bust the Data Cache for product pages without touching the Full Route Cache.
  • A team sets cache: 'no-store' on a user-specific fetch so it bypasses the Data Cache and always hits the origin.
  • A build pipeline benefits from the Full Route Cache serving static pages from disk without running any React render code.

More examples

Data Cache: store indefinitely

force-cache stores the response in the Data Cache and the tag lets you invalidate it later with revalidateTag.

Example · ts
// Stored in the Data Cache until manually invalidated
const res = await fetch('https://api.example.com/settings', {
  cache: 'force-cache',
  next: { tags: ['settings'] },
});
const settings = await res.json();

Skip the Data Cache

no-store bypasses both the Data Cache and the Full Route Cache, ensuring live data on every request.

Example · ts
// Always fetched fresh — no Data Cache entry created
const res = await fetch('https://api.example.com/live-price', {
  cache: 'no-store',
});
const price = await res.json();

Invalidate cache on mutation

Calling revalidateTag purges all cached fetch responses tagged with 'settings' across every route.

Example · ts
'use server';
import { revalidateTag } from 'next/cache';

export async function updateSettings(data: Record<string, string>) {
  await db.settings.update({ data });
  revalidateTag('settings'); // clears Data Cache entries with this tag
}

Discussion

  • Be the first to comment on this lesson.