Back to roadmaps nextjs Course

Caching and Revalidation

Next.js optimizes performance by caching data aggressively. It manages a multi-layer cache that spans request lifecycles, database operations, static pages, and client-side router transitions.


1. The Four-Layer Cache Architecture

Here is how Next.js handles caching across the lifecycle:

  • Request Memoization: Caches duplicate fetch requests with identical URLs and parameters within a single server request lifetime. This allows you to call the same fetch function in multiple components without paying a performance penalty.
  • Data Cache: Persists data across user sessions and server restarts until manually invalidated.
  • Full Route Cache: Stores the compiled HTML and React Server Component payload of static pages at build time.
  • Router Cache: Client-side memory cache that stores visited routes in the browser during a user session, ensuring immediate back-and-forth navigation.

2. Configuring Cache Behavior

You can customize fetch cache behavior using the standard fetch configuration options:

// 1. Cache the response globally (Default behavior)
fetch("https://api.example.com", { cache: "force-cache" });

// 2. Disable cache completely, fetching live data on every call
fetch("https://api.example.com", { cache: "no-store" });

// 3. Cache the response for a specific time limit (in seconds)
fetch("https://api.example.com", { next: { revalidate: 3600 } });

3. On-Demand Revalidation

Sometimes you need to purge the cache instantly when database records change (for example, when a user edits an article or submits a product review). Next.js supports on-demand revalidation using two API helpers:

Revalidating by Path

Clears the cache for a specific route path:

import { revalidatePath } from "next/cache";

// Purge cache for all users visiting the blog overview page
revalidatePath("/blog");

Revalidating by Tag

A cleaner approach is grouping fetch requests using a custom cache tag, and then invalidating that tag:

// Step 1: Assign a custom tag to your fetch request
fetch("https://api.example.com/products", {
  next: { tags: ["product-list"] }
});

// Step 2: Trigger revalidation elsewhere (e.g., in a Server Action)
import { revalidateTag } from "next/cache";

async function handleNewProductSubmit() {
  // Purges only the database cache matching this tag
  revalidateTag("product-list");
}
Published on Last updated: