AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

ISR Revalidation Retains RSC Segment Data Via CachedParams WeakMap (External/ArrayBuffers Growth, Amplified On Node 22)

Next.js ISR revalidation retains RSC segment buffers through a module-scope CachedParams WeakMap whose cached promises capture AsyncLocalStorage context, causing external memory (arrayBuffers) to accumulate until full GC; production impact up to 1.16 GB retained.

criticalConfidence 85%Next.jsAffected V16.2.7Affected V16.2.8Affected V16.2.9Affected V16.2.10Affected V16.2.11Affected V16.2.12

Origin Analysis

Module-scope CachedParams WeakMap caches promises created inside AsyncLocalStorage contexts. The cached promise retains its ALS store (via V8 hidden fields), which through work store's onError roots the render's RSC segmentData buffers. On Node 22, full GCs are infrequent, allowing external memory to accumulate.
1. Clone https://github.com/udohsolomon/nextjs-isr-leak-repro 2. npm install && npm run build 3. npm run start > server.log 2>&1 & 4. node drive.mjs server.log 25 5. Observe process.memoryUsage().arrayBuffers growth over rounds, especially on Node 22.x

Fixing Code Block

Edge Case Audit

Deleting the cache entry after settlement eliminates cross-request deduplication for the same params. Under high concurrency or when params are reused often, this may increase CPU and async work. The temporary promise created by the then() call itself briefly captures the current ALS context, but is not stored and becomes collectable after settlement. If performance regresses, revert and apply Node 24 or reduce --max-old-space-size as a temporary workaround. A longer-term fix should avoid storing promises that capture ALS contexts (e.g., cache resolved values outside the ALS run or use AsyncLocalStorage.enterWith).

Ecosystem Topology