vercel/next.js
Caching
Three caching layers in the framework, in increasing order of granularity:
- Incremental cache — full-page HTML and JSON for ISR / SSG.
- Fetch cache (
patch-fetch.ts) — per-request memoization offetch()calls in server code. - Use cache — the new
'use cache'directive that caches arbitrary server function results.
Cache components, the umbrella feature, ties these together. When __NEXT_CACHE_COMPONENTS=true, most app-dir pages enable PPR implicitly and the framework's caching defaults shift toward stale-while-revalidate by default.
Incremental cache
packages/next/src/server/lib/incremental-cache/ is the pre-existing on-disk cache for full-page renders, JSON props, and image-optimizer output.
- In-memory layer — LRU cache for hot pages.
- On-disk layer —
.next/cache/directory with per-route subdirectories. - Pluggable handlers — users can swap to Redis or any custom store via
cacheHandlerinnext.config.js.
Built-in handlers under packages/next/src/server/lib/incremental-cache/:
| Handler | When |
|---|---|
file-system-cache.ts |
Default. Writes to .next/cache/ |
fetch-cache.ts |
Default for fetched data |
The cache implementation tracks revalidation through packages/next/src/server/lib/cache-handlers/ — these are the per-data-kind cache entries (e.g., a separate handler for prerender HTML vs JSON props).
Fetch cache (patch-fetch)
packages/next/src/server/lib/patch-fetch.ts (47 KB) is one of the largest single files in the runtime. It monkey-patches the global fetch() to:
- Memoize identical requests within a single render (deduplication).
- Cache responses across renders, scoped to the work-unit async storage.
- Honor revalidation via
next.revalidate/next.tagsrequest options. - Trigger revalidation when
revalidatePathorrevalidateTagis called.
graph TD
UserFetch[await fetch(url, opts)] --> Patched[patched fetch]
Patched --> Memo{In-memory<br/>memoization?}
Memo -- hit --> Return[return memoized]
Memo -- miss --> CheckCache{In incremental<br/>cache?}
CheckCache -- hit + fresh --> Return
CheckCache -- hit + stale --> Background[background revalidate<br/>return stale]
CheckCache -- miss --> RealFetch[do real fetch]
RealFetch --> WriteCache[write to incremental cache]
WriteCache --> Memo2[memoize in render]
Memo2 --> ReturnA separate dedupe-fetch.ts (4 KB) handles request deduplication for the App Router specifically — multiple components rendering against the same fetch() call get the same promise.
Use cache
packages/next/src/server/use-cache/use-cache-wrapper.ts (2,861 lines) implements the 'use cache' directive. When a server function declares 'use cache', the framework:
- Compiles it via the SWC transform that recognizes the directive.
- Wraps the function with cache machinery: a stable cache key derived from arguments, lookup against the cache handler, write-on-miss behavior.
- Tracks cache scope through
work-unit-async-storage.external.ts.
The cache key is derived from the function's source location plus the arguments (after they're encoded). The cache handler is the same pluggable layer used by the incremental cache.
Other files under packages/next/src/server/use-cache/:
cache-handler.ts— the dispatch to the configured cache handlercache-life.ts— thecacheLifeAPI for setting per-call TTLscache-tag.ts— thecacheTagAPI for invalidation by tagcrypto-key.ts— derives encryption keys for cached valuesdefault-cache-life.ts— default cache lifetimes by profile name
Cache components
The umbrella feature flag __NEXT_CACHE_COMPONENTS=true enables:
- PPR by default for app-dir pages.
- A unified caching surface via
'use cache'. - Different default revalidation behavior (stale-while-revalidate becomes the norm).
The legacy ppr-full/ and ppr/ test suites are mostly describe.skip while this migration completes — to test PPR codepaths today, run normal app-dir e2e tests with the cache components flag set.
Revalidation
Three APIs trigger cache invalidation:
| API | Effect |
|---|---|
revalidatePath(path) |
Invalidates all cache entries tagged for this path |
revalidateTag(tag) |
Invalidates all cache entries with this tag |
next.revalidate: <s> |
Per-fetch TTL |
Implementation: packages/next/src/server/revalidation-utils.ts. The router-server checks the revalidation flags after each response and may trigger background re-renders.
ISR (Incremental Static Regeneration)
ISR is an emergent behavior of the incremental cache: a page with getStaticProps + revalidate: 60 gets served from disk for 60 seconds, then re-fetched in the background. After regeneration, the new HTML replaces the old.
The implementation is the cooperation between:
incremental-cache/(storage)static-paths-worker.ts(regeneration in a worker)revalidation-utils.ts(TTL accounting)
Implicit tags
packages/next/src/server/lib/implicit-tags.ts (3 KB) generates implicit cache tags for incoming requests so framework operations (revalidation by path, revalidation by tag) can be coordinated even when the user doesn't supply explicit tags.
Stale-time and cache-control
packages/next/src/server/app-render/stale-time.ts and packages/next/src/server/lib/cache-control.ts produce the Cache-Control headers attached to responses. The headers reflect the per-route rendering mode (static, ISR, dynamic) and any revalidate config.
Disk LRU
packages/next/src/server/lib/disk-lru-cache.external.ts provides a generic disk-backed LRU used by the incremental cache and the image optimizer.
Integration points
- Patches the global
fetchonce, on first render in a render scope. - Uses async storage to know "we are inside a render" — bare
fetch()calls outside a render context behave normally. - Coordinates with the build pipeline through
prerender-manifest.json. - Honors user-supplied
cacheHandlerfor both ISR and'use cache'.
Entry points for modification
- To change fetch-cache behavior:
packages/next/src/server/lib/patch-fetch.ts. - To change the use-cache wrapper:
packages/next/src/server/use-cache/use-cache-wrapper.ts. - To add a new revalidation primitive:
packages/next/src/server/revalidation-utils.tsplus the public re-export underpackages/next/src/api/cache.ts. - To add a cache handler kind:
packages/next/src/server/lib/cache-handlers/.
Key source files
| File | Purpose |
|---|---|
packages/next/src/server/lib/incremental-cache/ |
ISR / SSG / fetch on-disk cache |
packages/next/src/server/lib/patch-fetch.ts |
Patched global fetch |
packages/next/src/server/lib/dedupe-fetch.ts |
App Router fetch deduplication |
packages/next/src/server/use-cache/use-cache-wrapper.ts |
'use cache' runtime |
packages/next/src/server/use-cache/cache-handler.ts |
Cache handler dispatch |
packages/next/src/server/use-cache/cache-life.ts |
cacheLife API |
packages/next/src/server/use-cache/cache-tag.ts |
cacheTag API |
packages/next/src/server/revalidation-utils.ts |
revalidatePath, revalidateTag plumbing |
packages/next/src/server/lib/implicit-tags.ts |
Implicit tags from request shape |
packages/next/src/server/app-render/stale-time.ts |
Cache-Control header generation |
packages/next/src/server/lib/cache-handlers/ |
Per-data-kind handler implementations |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.