Caching & Revalidation
Three layers — full-route, data, and Router cache — and the levers that control each one.
Caching is what makes a Next.js site feel fast and what trips most people up the first time. There are three layers, each with a clear job.
1. Full-route cache (the HTML)
Static routes are prerendered to HTML at build time and cached. Visitors get bytes off the CDN. Dynamic routes skip this layer and render on every request.
Control with dynamic, revalidate and the rules from lesson 12.
2. Data cache (the fetches)
Individual fetch() calls can be cached independently. This is what lets two pages share a cached API response.
// Cached indefinitely:
await fetch(url, { cache: "force-cache" });
// Cached for 60 seconds:
await fetch(url, { next: { revalidate: 60 } });
// Never cached:
await fetch(url, { cache: "no-store" });
// Cached + tagged for targeted purges:
await fetch(url, { next: { tags: ["posts"] } });In Next.js 16, fetch is not cached by default — you opt in. This is a deliberate change to remove caching surprises.
3. Router cache (in-memory in the browser)
Once a route is loaded in the browser, the router keeps it in memory for a short while. Navigating back is instant. You can bust it from a client component using router.refresh().
On-demand revalidation
After a mutation, purge the relevant caches:
import { revalidatePath, revalidateTag } from "next/cache";
// Purge HTML + data for a route:
revalidatePath("/posts");
// Purge every fetch tagged "posts":
revalidateTag("posts");revalidatePath and revalidateTag work inside server actions and route handlers. They do not return data — they mark caches as stale so the next request rebuilds.
A mental model
- Static = the HTML is cached at the edge.
- Fetches = each network call has its own cache key and policy.
- Tags = how you group fetches so you can invalidate them by purpose, not by URL.
- Mutations call
revalidatePathorrevalidateTagto surface fresh data.
Try it
After deleting a post, the `/posts` page still shows the deleted item. Add the right call so the list refreshes.
Need a hint?
Import revalidatePath from next/cache and call it after the delete.
Quiz
Pick the best answer. You only get one shot per question.
1. In Next.js 16, `fetch(url)` with no options inside a server component is:
2. You tagged fetches with `tags: ['posts']`. How do you invalidate them all in one call?
3. Where can you call `revalidatePath` and `revalidateTag`?