Foundations
The Next.js 16 caching model
Lesson 2 of 7
What you'll learn
- Understand why Next.js 16 made caching explicit
- Use
use cacheto cache expensive, shareable work - Know what should never be cached (per-user data)
Earlier versions of Next.js cached aggressively and implicitly — which led to a lot of "why is my data stale?" confusion. Next.js 16 flips this: nothing is cached unless you ask for it. All dynamic code runs at request time by default.
Opting into the cache
You mark a function or component as cacheable with the use cache directive, and tune its lifetime with cacheLife and cacheTag:
import { unstable_cacheLife as cacheLife } from "next/cache";
async function getCourseCatalog() {
"use cache";
cacheLife("hours");
return db.courses.findMany();
}
Cache things that are shared across users and change rarely: a marketing page, a published course catalog, lesson content. Keep things per-user and live — progress, entitlements, the signed-in user — dynamic.
Never cache identity
A signed-in user's progress or permissions must render fresh every request. Cache the lesson content (same for everyone); never cache whether this user finished it.
Invalidation
When content changes, you invalidate by tag rather than waiting for a timer:
import { revalidateTag } from "next/cache";
// after a publish webhook fires:
revalidateTag("course-catalog");
The exercise below is a tiny model of cache-vs-fresh. The getCached function pretends to be expensive; run it twice and watch the cache hit on the second call.
Run it. The first call 'computes'; the second is served from the cache. Try clearing the cache and running again.
Next up: real data. We'll design a Convex schema and learn why indexes are mandatory.
Sign in to save your progress across devices.