Skip to content

Conversation

@icyJoseph
Copy link
Collaborator

No description provided.

@ijjk ijjk added created-by: Next.js DevEx team PRs by the DX team. Documentation Related to Next.js' official documentation. labels Oct 24, 2025
@icyJoseph icyJoseph marked this pull request as ready for review October 28, 2025 15:21
Comment on lines +260 to +335
```js filename="cache-handlers/external-handler.js"
module.exports = class ExternalCacheHandler {
async get(cacheKey, softTags) {
// Retrieve from external storage
const stored = await externalStorage.get(cacheKey)
if (!stored) {
return undefined
}

// Deserialize the entry
// Note: You'll need to reconstruct the ReadableStream from stored data
const entry = {
value: new ReadableStream({
start(controller) {
controller.enqueue(stored.data)
controller.close()
},
}),
tags: stored.tags,
stale: stored.stale,
timestamp: stored.timestamp,
expire: stored.expire,
revalidate: stored.revalidate,
}

return entry
}

async set(cacheKey, pendingEntry) {
const entry = await pendingEntry

// Read the stream to get the data
const reader = entry.value.getReader()
const chunks = []

try {
while (true) {
const { done, value } = await reader.read()
if (done) break
chunks.push(value)
}
} finally {
reader.releaseLock()
}

// Combine chunks and store to external storage
const data = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)))

await externalStorage.set(cacheKey, {
data,
tags: entry.tags,
stale: entry.stale,
timestamp: entry.timestamp,
expire: entry.expire,
revalidate: entry.revalidate,
})
}

async refreshTags() {
// Sync with external tag service if applicable
// await externalTagService.refresh()
}

async getExpiration(tags) {
// Query external service for tag expiration
// const expiration = await externalTagService.getExpiration(tags)
// return expiration
return 0
}

async updateTags(tags, durations) {
// Update external tag service
// await externalTagService.updateTags(tags, durations)
}
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "External storage pattern" code example uses an undefined variable externalStorage without explaining that it's a placeholder. This could confuse developers trying to implement custom cache handlers.

View Details
📝 Patch Details
diff --git a/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheHandlers.mdx b/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheHandlers.mdx
index f3e153bfe3..7839362c11 100644
--- a/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheHandlers.mdx
+++ b/docs/01-app/03-api-reference/05-config/01-next-config-js/cacheHandlers.mdx
@@ -258,6 +258,8 @@ module.exports = class MemoryCacheHandler {
 For durable storage like Redis or a database, you'll need to serialize the cache entries:
 
 ```js filename="cache-handlers/external-handler.js"
+// Note: `externalStorage` should be replaced with your actual storage implementation
+// (e.g., Redis client, database connection, Memcached client, etc.)
 module.exports = class ExternalCacheHandler {
   async get(cacheKey, softTags) {
     // Retrieve from external storage

Analysis

Undefined placeholder variable externalStorage not explained in documentation

What fails: The "External storage pattern" code example in cacheHandlers.mdx uses the undefined variable externalStorage.get() and externalStorage.set() without explaining that it's a placeholder that needs to be replaced with an actual implementation.

How to reproduce: Open docs/01-app/03-api-reference/05-config/01-next-config-js/cacheHandlers.mdx and read the "External storage pattern" section (lines 260-335). The code shows:

const stored = await externalStorage.get(cacheKey)
// ...
await externalStorage.set(cacheKey, { ... })

Result: Developers reading this example may not understand that externalStorage is a placeholder and must be replaced with their own storage client (Redis, Memcached, database, etc.), causing confusion when implementing custom cache handlers.

Expected behavior: The section introduction states "For durable storage like Redis or a database, you'll need to serialize the cache entries" but doesn't explicitly explain that externalStorage is a placeholder needing implementation. By contrast, the "Basic in-memory cache handler" example shows a complete working implementation using Map, and the self-hosting guide uses explicit comments like "// This could be stored anywhere, like durable storage" for similar placeholders.

Fix applied: Added a clarifying comment at the top of the ExternalCacheHandler class explaining that externalStorage is a placeholder that should be replaced with an actual storage implementation (e.g., Redis client, database connection, Memcached client).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

created-by: Next.js DevEx team PRs by the DX team. Documentation Related to Next.js' official documentation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants