---
title: "Incremental Cache"
description: "The Incremental Cache powers Next.js rendering optimization and incremental static regeneration (ISR) by persisting and retrieving prerendered routes, data fetches, and function outputs across requ..."
last_updated: "2026-09-23T10:52:03.199778+00:00"
canonical_url: "https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/caching-and-export/incremental-cache"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/next/src/server/lib/patch-fetch.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-fetch.ts)
- [packages/next/src/server/response-cache/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts)
- [packages/next/src/server/lib/incremental-cache/index.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/index.ts)
- [packages/next/src/server/use-cache/use-cache-wrapper.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts)
- [packages/next/src/server/web/spec-extension/unstable-cache.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/unstable-cache.ts)
- [packages/next/src/client/components/segment-cache/cache.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts)
- [packages/next/src/server/lib/incremental-cache/file-system-cache.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts)
- [packages/next/src/server/route-modules/route-module.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/route-module.ts)
- [packages/next/src/server/web/spec-extension/revalidate.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts)
- [packages/next/src/server/revalidation-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/revalidation-utils.ts)
- [packages/next/src/server/response-cache/types.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/types.ts)
- [packages/next/src/server/app-render/instant-validation/instant-validation.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx)
- [packages/next/src/server/app-render/collect-segment-data.tsx](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/collect-segment-data.tsx)
- [packages/next/src/client/dev/debug-channel.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/client/dev/debug-channel.ts)
- [packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts)
- [packages/next/src/server/use-cache/cache-tag.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/cache-tag.ts)
- [packages/next/src/server/lib/dedupe-fetch.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dedupe-fetch.ts)
- [packages/next/src/server/lib/encode-cache-tag.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/encode-cache-tag.ts)
- [packages/next/src/server/route-modules/app-route/module.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-route/module.ts)
- [packages/next/src/shared/lib/page-path/ensure-leading-slash.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/page-path/ensure-leading-slash.ts)
- [packages/next/src/shared/lib/page-path/normalize-page-path.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/page-path/normalize-page-path.ts)
</details>

## Overview

The Incremental Cache powers Next.js rendering optimization and incremental static regeneration (ISR) by persisting and retrieving prerendered routes, data fetches, and function outputs across requests. It bridges server-side render pipelines and persistent backends—such as the default file system cache or custom cache handlers—to eliminate redundant computation and database queries. By integrating request deduplication, cache tag invalidation, and client segment coordination, the incremental cache subsystem ensures data freshness while maintaining high-performance response streaming.

Sources: [packages/next/src/server/lib/incremental-cache/index.ts:83-95](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/index.ts#L83-L95), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:36-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L36-L63)

## IncrementalCache Core Architecture

### Overview

The `IncrementalCache` subsystem manages persistent caching across Next.js rendering operations by implementing the `IncrementalCache` and `CacheHandler` interfaces. It coordinates between in-memory caches, disk storage via `FileSystemCache`, and custom pluggable cache handlers. When a cache lookup is requested, the system inspects route metadata, file modification times (`mtime`), and tag expiration states to determine whether a stored entry is fresh, stale, or expired.

Sources: [packages/next/src/server/lib/incremental-cache/index.ts:39-81](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/index.ts#L39-L81), [packages/next/src/server/lib/incremental-cache/index.ts:83-105](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/index.ts#L83-L105), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:36-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L36-L63)

### Cache Handler and Core Interfaces

The cache architecture relies on explicit TypeScript interfaces that define the contract for retrieving, storing, and revalidating cache entries across different cache kinds.

| Interface / Class | Key Members / Methods | Purpose |
| :--- | :--- | :--- |
| `CacheHandler` | `constructor(ctx)`, `get(key, ctx)`, `set(key, data, ctx)`, `revalidateTag(tags, durations)`, `resetRequestCache()` | Base class defining the mandatory handler contract for custom and built-in cache backends. |
| `CacheHandlerContext` | `fs`, `dev`, `flushToDisk`, `serverDistDir`, `maxMemoryCacheSize`, `fetchCacheKeyPrefix`, `prerenderManifest`, `revalidatedTags`, `_requestHeaders` | Configuration context passed to cache handlers upon initialization. |
| `IncrementalCache` | `get(cacheKey, ctx)`, `set(key, data, ctx)`, `revalidateTag(tags, durations)` | Concrete implementation fulfilling response and fetch caching requirements. |
| `FileSystemCache` | `memoryCache`, `get(...)`, `set(...)`, `revalidateTag(...)` | Default file-system and LRU memory-backed implementation of `CacheHandler`. |

Sources: [packages/next/src/server/lib/incremental-cache/index.ts:39-81](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/index.ts#L39-L81), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:36-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L36-L63)

### File System Persistence and Retrieval

The `FileSystemCache` manages multi-format assets on disk, distinguishing between `APP_ROUTE`, `APP_PAGE`, `PAGES`, and `FETCH` cache kinds. When retrieving items, it checks the LRU memory cache before falling back to file system reads via `this.fs.readFile` and `this.fs.stat`.

```mermaid
sequenceDiagram
    participant Caller
    participant IncrementalCache
    participant FileSystemCache
    participant LRUMemory as Memory Cache (LRU)
    participant Disk as File System (fs)

    Caller->>IncrementalCache: get(cacheKey, ctx)
    IncrementalCache->>FileSystemCache: get(key, ctx)
    FileSystemCache->>LRUMemory: get(key)
    alt Memory Hit
        LRUMemory-->>FileSystemCache: return cached data
    else Memory Miss
        FileSystemCache->>Disk: readFile / stat (HTML, RSC, body, metadata)
        Disk-->>FileSystemCache: return raw file data & mtime
        FileSystemCache->>LRUMemory: set(key, data)
    end
    FileSystemCache-->>IncrementalCache: return CacheHandlerValue
```

Sources: [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:105-120](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L105-L120), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:121-296](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L121-L296)

### Design Trade-Offs

| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| **LRU Memory Cache layer in front of Disk** | Eliminates redundant I/O operations for frequently accessed fetch and route data. | Consumes heap memory bounded by `maxMemoryCacheSize`. |
| **Separate file extensions (`.html`, `.body`, `.rsc`, `.meta`)** | Avoids complex serialization of mixed payloads; allows independent reads of headers and bodies. | Results in multiple file system operations per cached page. |
| **Global cache handler symbol resolution (`@next/cache-handlers`)** | Enables external third-party custom cache handlers to be injected globally. | Requires runtime symbol lookup and indirection during instantiation. |

Sources: [packages/next/src/server/lib/incremental-cache/index.ts:133-162](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/index.ts#L133-L162), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:50-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L50-L63), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:121-256](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L121-L256)

> [!WARNING]
> When `flushToDisk` is disabled or running in edge runtime (`NEXT_RUNTIME === 'edge'`), `FileSystemCache` bypasses disk reads for fetch caches or limits persistence, relying entirely on memory or throwing invariant errors if unexpected route kinds are encountered.

Sources: [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:120-121](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L120-L121), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:157-158](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L157-L158), [packages/next/src/server/lib/incremental-cache/file-system-cache.ts:283-287](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/file-system-cache.ts#L283-L287)

## Response Cache and Request Batching

### Overview

The response cache manages in-memory caching and request deduplication for generated responses. It relies on an LRU storage engine configured via environment variables and uses a batcher utility to ensure that concurrent, identical render requests share a single inflight operation.

Sources: [packages/next/src/server/response-cache/index.ts:9-12](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L9-L12), [packages/next/src/server/response-cache/index.ts:53-56](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L53-L56)

### Configuration and LRU Storage

In-memory caching behavior is governed by tunable constants parsed from environment variables. These parameters control default Time-To-Live (TTL) values and maximum storage sizes.

| Constant | Environment Variable | Default Value | Purpose |
| :--- | :--- | :--- | :--- |
| `DEFAULT_TTL_MS` | `NEXT_PRIVATE_RESPONSE_CACHE_TTL` | `10000` (10s) | Fallback TTL for cache hit validation when providers omit invocation headers. |
| `DEFAULT_MAX_SIZE` | `NEXT_PRIVATE_RESPONSE_CACHE_MAX_SIZE` | `150` | Maximum number of entries stored in the LRU response cache. |

Sources: [packages/next/src/server/response-cache/index.ts:44-56](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L44-L56)

> [!NOTE]
> Compound cache keys combine pathnames and invocation identifiers separated by a null byte (`\0`), ensuring isolation across distinct render invocations. When an invocation identifier is missing, a reserved `__ttl_sentinel__` marker is used.

Sources: [packages/next/src/server/response-cache/index.ts:58-68](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L58-L68)

### Request Deduplication via Batching

When multiple concurrent callers request the same cache key, duplicate render executions are prevented using a batching mechanism. The call chain routes requests through the cache lookup layer and coordinates revalidations:

`handleGet()` → `revalidate()` → `revalidateBatcher.batch()` → `handleRevalidate()` → `responseGenerator()`

Sources: [packages/next/src/server/response-cache/index.ts:318-331](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L318-L331), [packages/next/src/server/response-cache/index.ts:418-427](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L418-L427), [packages/next/src/server/response-cache/index.ts:428-444](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L428-L444), [packages/next/src/server/response-cache/index.ts:446-461](https://github.com/blade47/next.js/blob/main/packages/next/src/server/response-cache/index.ts#L446-L461)

## Fetch Patching and Request Deduplication

### Overview

Next.js intercepts and patches the global `fetch` API during route execution to integrate automatic request deduplication and incremental caching. Global fetch monkey-patching ensures that standard `fetch()` calls executed within server components, route handlers, or page components flow through specialized wrappers capable of tracking metrics, enforcing cache rules, and sharing inflight promises across concurrent calls.

Sources: [packages/next/src/server/lib/patch-fetch.ts:427-430](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/patch-fetch.ts#L427-L430), [packages/next/src/server/route-modules/app-route/module.ts:22-22](https://github.com/blade47/next.js/blob/main/packages/next/src/server/route-modules/app-route/module.ts#L22-L22)

### Request Deduplication and Cache Key Generation

The deduplication wrapper (`dedupeFetch`) handles incoming request arguments by normalizing string URLs or `Request` instances into a structured cache key via `generateCacheKey`. Requests possessing side effects (such as `POST`, `PUT`, `DELETE`, or `PATCH` methods, or those with `keepalive` enabled) bypass deduplication and execute directly against the original `fetch`.

Sources: [packages/next/src/server/lib/dedupe-fetch.ts:44-89](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dedupe-fetch.ts#L44-L89)

| Component Property | Included in Dedupe Key? | Purpose / Handling |
| :--- | :--- | :--- |
| `request.method` | Yes | Differentiates GET, HEAD, and other HTTP operations. |
| `request.headers` | Yes (Filtered) | Includes headers excluding distributed tracing entries (`traceparent`, `tracestate`). |
| `request.mode` | Yes | Specifies navigation or CORS mode. |
| `request.redirect` | Yes | Controls how redirects are handled (`follow`, `error`, `manual`). |
| `request.credentials` | Yes | Determines credential inclusion (`omit`, `same-origin`, `include`). |
| `request.referrer` | Yes | Specifies the referrer URL. |
| `request.referrerPolicy` | Yes | Governs referrer header population. |
| `request.integrity` | Yes | Subresource integrity verification hash. |

Sources: [packages/next/src/server/lib/dedupe-fetch.ts:10-36](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dedupe-fetch.ts#L10-L36)

> [!NOTE]
> Passing an explicit `AbortSignal` via `options.signal` acts as an opt-out mechanism for request deduplication, forcing `dedupeFetch` to skip the in-memory cache layer and execute `originalFetch` immediately.

Sources: [packages/next/src/server/lib/dedupe-fetch.ts:54-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dedupe-fetch.ts#L54-L63)

## Cache Tag Invalidation Pipeline

### Overview

The cache tag invalidation pipeline manages on-demand purging of cached data and incremental static regeneration (ISR) state through tag encoding, revalidation triggering, and tags manifest synchronization. When developers invalidate cached data via user-facing functions such as `revalidateTag`, `updateTag`, or `revalidatePath`, inputs are processed and normalized to ensure wire and storage consistency before being dispatched through asynchronous execution boundaries.

Sources: [packages/next/src/server/web/spec-extension/revalidate.ts:34-41](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L34-L41), [packages/next/src/server/web/spec-extension/revalidate.ts:49-63](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L49-L63), [packages/next/src/server/web/spec-extension/revalidate.ts:97-123](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L97-L123)

### Tag Encoding and Normalization

To prevent Node.js header validation errors (such as `ERR_INVALID_CHAR`) when tag names or route paths contain non-ASCII characters or run-time unicode symbols, tag inputs pass through `encodeCacheTag`. This function evaluates strings against printable ASCII rules and percent-encodes out-of-class character runs while preserving structural separators like commas, forward slashes, and dynamic segment markers.

Sources: [packages/next/src/server/lib/encode-cache-tag.ts:1-37](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/encode-cache-tag.ts#L1-L37)

Path-based revalidations handled by `revalidatePath` normalize paths by removing trailing slashes, attaching implicit tag prefixes (`NEXT_CACHE_IMPLICIT_TAG_ID`), and appending layout or page types. If a normalized path points to a root or index location, sibling variants are automatically added to the tag array to keep cache references synchronized.

Sources: [packages/next/src/server/web/spec-extension/revalidate.ts:97-123](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L97-L123)

| Invalidation Function | Context Restriction | Target Profile / Expiration Behavior |
| :--- | :--- | :--- |
| `revalidateTag` | Outside render / cached functions | Accepts a profile string or `CacheLifeConfig` object (deprecated single argument logs warning). |
| `updateTag` | Server Action only | Immediate expiration (`undefined` profile) to enforce read-your-own-writes semantics. |
| `revalidatePath` | Outside render / cached functions | Normalizes original path with implicit tags and optional layout/page specifiers. |
| `refresh` | Server Action only | Sets `workStore.pathWasRevalidated = ActionDidRevalidateDynamicOnly` on the client. |

Sources: [packages/next/src/server/web/spec-extension/revalidate.ts:34-90](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L34-L90), [packages/next/src/server/web/spec-extension/revalidate.ts:97-123](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L97-L123)

### Revalidation Triggering and Execution Pipeline

When a revalidation function is invoked, it validates work store state and checks the active `workUnitStore` phase. Calling revalidation methods inside a render phase, cache wrapper, or `generateStaticParams` throws an immediate error or triggers runtime suspension. Valid tags are pushed into `store.pendingRevalidatedTags` and processed via runtime helper wrappers.

Sources: [packages/next/src/server/web/spec-extension/revalidate.ts:130-229](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L130-L229)

The revalidation flow follows a structured execution sequence managed by lifecycle wrapper routines:

`withExecuteRevalidates()` → `cloneRevalidationState()` → `callback()` → `diffRevalidationState()` → `executeRevalidates()` → `revalidateTags()`

Sources: [packages/next/src/server/revalidation-utils.ts:6-26](https://github.com/blade47/next.js/blob/main/packages/next/src/server/revalidation-utils.ts#L6-L26), [packages/next/src/server/revalidation-utils.ts:186-221](https://github.com/blade47/next.js/blob/main/packages/next/src/server/revalidation-utils.ts#L186-L221)

> [!WARNING]
> Invoking `revalidateTag`, `updateTag`, or `revalidatePath` directly during a React component render or inside a `use cache` body will throw an error. Revalidation must always execute outside of renders and cached functions to ensure consistency.

Sources: [packages/next/src/server/web/spec-extension/revalidate.ts:137-154](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/revalidate.ts#L137-L154)

### Tags Manifest Synchronization and Expiration Checks

The `tagsManifest` map shares state between "use cache" handlers and file-system caches using `TagManifestEntry` definitions. During cache evaluation, `areTagsExpired` and `areTagsStale` inspect manifest values against requested timestamps.

Sources: [packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts:3-43](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts#L3-L43)

```typescript
export interface TagManifestEntry {
  stale?: number
  expired?: number
}

export const tagsManifest = new Map<string, TagManifestEntry>()
```

Sources: [packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts:3-10](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts#L3-L10)

For immediate expiration checks, `areTagsExpired` calculates current performance times (`performance.timeOrigin + performance.now()`) to determine whether an entry's expiration threshold has elapsed relative to the target cache timestamp. Similarly, `areTagsStale` iterates through tag arrays to verify if recorded stale thresholds exceed baseline generation timestamps.

Sources: [packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts:12-43](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/incremental-cache/tags-manifest.external.ts#L12-L43)

## Function and Data Cache Wrapping

### Overview

Next.js caches and wraps expensive operations, database queries, and component trees through `unstable_cache` and the `'use cache'` directive infrastructure. These wrappers manage execution lifecycles, propagate cache metadata across asynchronous storage boundaries, handle cache invalidation conditions, and enforce timeout or revalidation rules.

Sources: [packages/next/src/server/web/spec-extension/unstable-cache.ts:56-60](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/unstable-cache.ts#L56-L60)

### Unstable Cache Execution and Lifecycle Walkthrough

When an `unstable_cache`-wrapped function is invoked, it passes through a deterministic sequence of async storage lookups, cache key generation, store configuration, and cache validation checks.

The execution flow proceeds as follows:

`unstable_cache` invocation (`cachedCb`) → `workAsyncStorage.getStore()` / `workUnitAsyncStorage.getStore()` → `incrementalCache.generateCacheKey()` → `incrementalCache.get()` → `cacheEntry.isStale` check (background revalidation vs. foreground blocking revalidation) → execution via `workUnitAsyncStorage.run(innerCacheStore, cb, ...args)` → `cacheNewResult()` or direct return.

Sources: [packages/next/src/server/web/spec-extension/unstable-cache.ts:100-310](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/unstable-cache.ts#L100-L310)

> [!WARNING]
> Passing an explicit `revalidate: 0` option to `unstable_cache()` throws an immediate invariant error at construction time. Revalidation values must be explicitly set to `false` or a positive number greater than zero (`> 0`).

Sources: [packages/next/src/server/web/spec-extension/unstable-cache.ts:72-76](https://github.com/blade47/next.js/blob/main/packages/next/src/server/web/spec-extension/unstable-cache.ts#L72-L76)

### Cache Tag Registration and Work Unit Validation

The `cacheTag()` utility registers custom tags against the active execution context. It enforces structural checks via `workUnitAsyncStorage`, ensuring that tags are only declared within valid cache scopes and throwing descriptive errors if called incorrectly.

Sources: [packages/next/src/server/use-cache/cache-tag.ts:4-32](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/cache-tag.ts#L4-L32)

```typescript
export function cacheTag(...tags: string[]): void {
  if (!process.env.__NEXT_USE_CACHE) {
    throw new Error(
      '`cacheTag()` is only available with the `cacheComponents` config.'
    )
  }

  const workUnitStore = workUnitAsyncStorage.getStore()

  switch (workUnitStore?.type) {
    case 'prerender':
    case 'prerender-client':
    case 'validation-client':
    case 'prerender-runtime':
    case 'prerender-ppr':
    case 'prerender-legacy':
    case 'request':
    case 'unstable-cache':
    case 'generate-static-params':
    case undefined:
      throw new Error(
        '`cacheTag()` can only be called inside a "use cache" function.'
      )
    case 'cache':
    case 'private-cache':
      break
    default:
      workUnitStore satisfies never
  }

  const validTags = validateTags(tags, '`cacheTag()`')

  if (!workUnitStore.tags) {
    workUnitStore.tags = validTags
  } else {
    workUnitStore.tags.push(...validTags)
  }
}
```

Sources: [packages/next/src/server/use-cache/cache-tag.ts:4-41](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/cache-tag.ts#L4-L41)

> [!NOTE]
> Calling `cacheTag()` outside of a valid `'use cache'` function context — such as during standard page requests or inside `generateStaticParams` — triggers an immediate error aborting execution.

Sources: [packages/next/src/server/use-cache/cache-tag.ts:13-26](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/cache-tag.ts#L13-L26)

### Cache Discard and Revalidation Evaluation Rules

When evaluating whether to serve or discard a cached entry, `shouldDiscardCacheEntry` and `shouldForceRevalidate` inspect implicit tags, recent revalidation flags, draft mode status, and work store headers.

Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:3282-3370](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L3282-L3370)

| Evaluation Check | Target Condition | Action Taken on Match |
| :--- | :--- | :--- |
| `entry.timestamp <= implicitTagsExpiration` | Entry created before implicit tags were revalidated | Discard cache entry (`return true`) |
| `isRecentlyRevalidatedTag` | Tag present in `previouslyRevalidatedTags` or `pendingRevalidatedTags` | Discard cache entry (`return true`) |
| `workStore.isOnDemandRevalidate` / `isDraftMode` | On-demand revalidation or draft mode active | Force revalidation (`return true`) |
| `cache-control === 'no-cache'` (Dev Server) | Request headers specify `no-cache` in dev mode | Force revalidation (`return true`) |

Sources: [packages/next/src/server/use-cache/use-cache-wrapper.ts:3286-3288](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L3286-L3288), [packages/next/src/server/use-cache/use-cache-wrapper.ts:3293-3293](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L3293-L3293), [packages/next/src/server/use-cache/use-cache-wrapper.ts:3323-3332](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L3323-L3332), [packages/next/src/server/use-cache/use-cache-wrapper.ts:3359-3367](https://github.com/blade47/next.js/blob/main/packages/next/src/server/use-cache/use-cache-wrapper.ts#L3359-L3367)

## Segment Cache and Prerender Hydration

### Overview

The client segment cache coordinates how route segments, prefetch streams, and prerender hydration payloads are stored, decoded, and validated. Responses from the server carry specialized byte markers and metadata that dictate whether a stream is partial or complete before ingestion into the cache.

Sources: [packages/next/src/client/components/segment-cache/cache.ts:3117-3127](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts#L3117-L3127), [packages/next/src/client/components/segment-cache/cache.ts:3215-3224](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts#L3215-L3224)

### Prefetch Stream Processing and Partial Byte Stripping

When runtime prefetch streams are received, `processRuntimePrefetchStream` strips leading control bytes using `stripIsPartialByte`, decodes the underlying React Server Components stream, and extracts vary parameters and stale times.

Sources: [packages/next/src/client/components/segment-cache/cache.ts:3163-3192](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts#L3163-L3192)

The byte marker prefix inspection follows a strict protocol:

| Byte Marker | Hex Value | Interpretation |
| :--- | :--- | :--- |
| `'#'` | `0x23` | Complete response |
| `'~'` | `0x7e` | Partial response |
| Unmarked | — | Fallback to `__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS` flag |

Sources: [packages/next/src/client/components/segment-cache/cache.ts:3232-3246](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts#L3232-L3246)

> [!NOTE]
> Valid RSC Flight rows start with a hex digit or a colon (`:`), ensuring that marker bytes (`#` or `~`) never collide with legitimate Flight data rows.

Sources: [packages/next/src/client/components/segment-cache/cache.ts:3217-3220](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts#L3217-L3220)

### Segment Traversal and Validation Planning

On the server side, instant validation builds route trees and traverses payload segments to coordinate validation boundaries and segment request keys. The traversal visits each route node and formats segment path strings using URL encoding conventions.

Sources: [packages/next/src/server/app-render/instant-validation/instant-validation.tsx:109-126](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx#L109-L126), [packages/next/src/server/app-render/instant-validation/instant-validation.tsx:182-188](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx#L182-L188)

```typescript
function stringifySegment(segment: Segment): SegmentPath {
  return (
    typeof segment === 'string'
      ? encodeURIComponent(segment)
      : encodeURIComponent(segment[0]) + '|' + segment[1] + '|' + segment[2]
  ) as SegmentPath
}
```

Sources: [packages/next/src/server/app-render/instant-validation/instant-validation.tsx:182-188](https://github.com/blade47/next.js/blob/main/packages/next/src/server/app-render/instant-validation/instant-validation.tsx#L182-L188)

> [!WARNING]
> Unmarked runtime prefetch responses behave differently depending on whether cached navigations are enabled globally; omitting the experimental flag changes response partiality defaults.

Sources: [packages/next/src/client/components/segment-cache/cache.ts:3232-3246](https://github.com/blade47/next.js/blob/main/packages/next/src/client/components/segment-cache/cache.ts#L3232-L3246)

## Related

- [Function Caching](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/caching-and-export/function-caching)
- [Response Cache](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/caching-and-export/response-cache)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/llms.txt) for all pages in this wiki.
