Make cacheMaxMemorySize: 0 and custom cache handlers fast in dev#94784
Merged
Conversation
Contributor
Tests PassedCommit: d9732ce |
Contributor
Stats cancelledCommit: d9732ce |
1c8d394 to
1a02771
Compare
5b3012d to
58dd3df
Compare
1a02771 to
21e5258
Compare
58dd3df to
7c1fd32
Compare
21e5258 to
5f096c7
Compare
lubieowoce
reviewed
Jun 13, 2026
lubieowoce
reviewed
Jun 13, 2026
| expire: 0, | ||
| value: new ReadableStream({ | ||
| start(controller) { | ||
| controller.enqueue(new Uint8Array(1)) |
Member
There was a problem hiding this comment.
we have a whole byte to play with, imho we should pick a funnier number like 42
Contributor
Author
There was a problem hiding this comment.
Are you testing whether I let my agent auto-address review feedback? 😉
Member
There was a problem hiding this comment.
ah he figured it out, pack it up everybody
well, i'd assume you wouldn't outsource making something funny to an agent, that's way too important!
7c1fd32 to
0352438
Compare
5f096c7 to
a3d155f
Compare
58c3656 to
1ff5b49
Compare
When Cache Components is enabled, `next dev` treats a `'use cache'` value as a miss and renders as if the cache were empty whenever the read does not resolve right away. Two development configurations triggered that even for values that were already cached, so warm reloads streamed slowly instead of serving the cached value: `cacheMaxMemorySize: 0` replaced the built-in default handler with a no-op stub, so nothing was cached at all, and custom cache handlers with a slow or remote `get` did not return in time. For the size-0 case, development now uses a real in-memory handler instead of the no-op stub, and the `'use cache'` wrapper forces a dynamic cache life (`revalidate: 0`, a 5-minute `expire`) for it, the same treatment private caches already receive, so every read serves the stale entry and re-warms a fresh one in the background. This also fixes the dev private handler, which was sized from `cacheMaxMemorySize` and so degraded to the no-op stub whenever `cacheMaxMemorySize: 0` was set. Custom cache handlers keep their configured cache life, since their backing owns it. Instead we put a fast built-in in-memory front handler in front of the configured one through the new `TieredCacheHandler`, which serves warm reads from the front, writes through to both tiers, and reconciles the front against the backing in the background, evicting the front entry when the backing no longer has it (the handler interface has no per-key delete, so it overwrites the entry with an already-expired copy). These dev-only handlers are kept out of the registered handler set and merged in only where tag operations iterate, so `revalidateTag` still reaches them. Everything is gated on `process.env.__NEXT_DEV_SERVER`, so production is unchanged: `cacheMaxMemorySize: 0` still caches nothing, private entries are still never persisted, and configured handlers are used directly. New development test suites cover the size-0 and custom-handler behavior.
1ff5b49 to
6075919
Compare
lubieowoce
approved these changes
Jun 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When Cache Components is enabled,
next devtreats a'use cache'value as a miss and renders as if the cache were empty whenever the read does not resolve right away. Two development configurations triggered that even for values that were already cached, so warm reloads streamed slowly instead of serving the cached value:cacheMaxMemorySize: 0replaced the built-in default handler with a no-op stub, so nothing was cached at all, and custom cache handlers with a slow or remotegetdid not return in time.For the size-0 case, development now uses a real in-memory handler instead of the no-op stub, and the
'use cache'wrapper forces a dynamic cache life (revalidate: 0, a 5-minuteexpire) for it, the same treatment private caches already receive, so every read serves the stale entry and re-warms a fresh one in the background. This also fixes the dev private handler, which was sized fromcacheMaxMemorySizeand so degraded to the no-op stub whenevercacheMaxMemorySize: 0was set.Custom cache handlers keep their configured cache life, since their backing owns it. Instead we put a fast built-in in-memory front handler in front of the configured one through the new
TieredCacheHandler, which serves warm reads from the front, writes through to both tiers, and reconciles the front against the backing in the background, evicting the front entry when the backing no longer has it (the handler interface has no per-key delete, so it overwrites the entry with an already-expired copy). These dev-only handlers are kept out of the registered handler set and merged in only where tag operations iterate, sorevalidateTagstill reaches them.Everything is gated on
process.env.__NEXT_DEV_SERVER, so production is unchanged:cacheMaxMemorySize: 0still caches nothing, private entries are still never persisted, and configured handlers are used directly. New development test suites cover the size-0 and custom-handler behavior.