nextjs - ✅(Solved) Fix Memory leak causing OOM still occurs in Next.js 16.0.10 (also tested with 16.0.1) when using output: standalone with fetch requests. [1 pull requests, 18 comments, 6 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#90433Fetched 2026-04-08 00:20:06
View on GitHub
Comments
18
Participants
6
Timeline
48
Reactions
6
Timeline (top)
commented ×18subscribed ×13mentioned ×10cross-referenced ×2

Fix Action

Fixed

PR fix notes

PR #90897: fix: backport memory leak fixes (FinalizationRegistry + LRU zero-size) to stable

Description (problem / solution / changelog)

Summary

Backports three critical memory leak fixes from canary to the 16.x stable branch. These fixes prevent ArrayBuffer/WriteWrap retention causing OOM kills in production output: standalone deployments.

Changes

  1. clone-response.ts: Register both tee'd response clones with FinalizationRegistry (from #88577)

    • Previously only cloned1 was registered. cloned2 (stored in caches) was never auto-cancelled, leaving its tee buffer (backed by ArrayBuffers) alive indefinitely.
  2. lru-cache.ts: Enforce minimum size of 1 and throw on zero-size entries (from #89040)

    • calculateSize returning 0 meant entries never incremented totalSize, so the eviction loop (totalSize > maxSize) never fired. The Map grew without bound.
  3. Caller fixes (filesystem.ts, next-dev-server.ts): Ensure all calculateSize callbacks return >= 1

Evidence

Heap dump from production (ARM64 ECS Fargate, Next.js 16.1.6, Node 22.22.0) at 1 GB ArrayBuffers:

  • 977 MB in 183 JSArrayBufferData objects (mostly 32 MB chunks)
  • Retainer chain: WriteWrap._chunks → GC roots (20/31 large ArrayBuffers)
  • Root cause: un-cancelled tee'd ReadableStream branches holding native HTTP write buffers
VersionAfter 60s loadAfter settling
16.1.6 stable663 MB (growing)663 MB+ (never reclaimed, OOM)
canary.791040 MB (peak)32 MB (back to baseline)

Related: #85914, #89033, #90433, #90895

Test plan

  • Existing lru-cache.test.ts updated for new set() return type and zero-size rejection
  • Verified on production ECS Fargate (ARM64): canary.79 with these fixes resolves the leak completely

Made with Cursor

Changed files

  • .gitattributes (modified, +3/-0)
  • .github/workflows/build_and_deploy.yml (modified, +2/-2)
  • .github/workflows/build_and_test.yml (modified, +7/-18)
  • .github/workflows/build_reusable.yml (modified, +8/-0)
  • .github/workflows/trigger_release.yml (modified, +3/-4)
  • Cargo.lock (modified, +260/-172)
  • Cargo.toml (modified, +10/-10)
  • crates/next-build-test/nextConfig.json (modified, +1/-0)
  • crates/next-custom-transforms/tests/loader/issue-30389/output.js (modified, +2/-2)
  • docs/01-app/01-getting-started/04-linking-and-navigating.mdx (modified, +1/-1)
  • docs/01-app/01-getting-started/05-server-and-client-components.mdx (modified, +187/-2)
  • docs/01-app/01-getting-started/06-cache-components.mdx (modified, +15/-6)
  • docs/01-app/01-getting-started/07-fetching-data.mdx (modified, +2/-2)
  • docs/01-app/01-getting-started/08-updating-data.mdx (modified, +4/-2)
  • docs/01-app/01-getting-started/13-fonts.mdx (modified, +214/-0)
  • docs/01-app/01-getting-started/16-proxy.mdx (modified, +2/-2)
  • docs/01-app/02-guides/content-security-policy.mdx (modified, +3/-1)
  • docs/01-app/02-guides/package-bundling.mdx (modified, +175/-34)
  • docs/01-app/02-guides/production-checklist.mdx (modified, +1/-1)
  • docs/01-app/02-guides/public-static-pages.mdx (added, +253/-0)
  • docs/01-app/02-guides/redirecting.mdx (modified, +9/-9)
  • docs/01-app/02-guides/scripts.mdx (modified, +4/-4)
  • docs/01-app/02-guides/upgrading/version-16.mdx (modified, +5/-3)
  • docs/01-app/03-api-reference/01-directives/use-cache-private.mdx (modified, +31/-7)
  • docs/01-app/03-api-reference/01-directives/use-cache.mdx (modified, +33/-1)
  • docs/01-app/03-api-reference/02-components/image.mdx (modified, +23/-0)
  • docs/01-app/03-api-reference/03-file-conventions/dynamic-routes.mdx (modified, +1/-1)
  • docs/01-app/03-api-reference/03-file-conventions/layout.mdx (modified, +4/-2)
  • docs/01-app/03-api-reference/04-functions/after.mdx (modified, +2/-2)
  • docs/01-app/03-api-reference/04-functions/cookies.mdx (modified, +9/-9)
  • docs/01-app/03-api-reference/04-functions/forbidden.mdx (modified, +1/-1)
  • docs/01-app/03-api-reference/04-functions/generate-metadata.mdx (modified, +64/-0)
  • docs/01-app/03-api-reference/04-functions/generate-viewport.mdx (modified, +46/-0)
  • docs/01-app/03-api-reference/04-functions/permanentRedirect.mdx (modified, +1/-1)
  • docs/01-app/03-api-reference/04-functions/redirect.mdx (modified, +1/-1)
  • docs/01-app/03-api-reference/04-functions/unauthorized.mdx (modified, +1/-1)
  • docs/01-app/03-api-reference/05-config/01-next-config-js/optimizePackageImports.mdx (modified, +1/-0)
  • docs/01-app/03-api-reference/06-cli/next.mdx (modified, +48/-9)
  • docs/01-app/04-glossary.mdx (added, +272/-0)
  • docs/02-pages/04-api-reference/03-functions/use-params.mdx (added, +242/-0)
  • docs/02-pages/04-api-reference/03-functions/use-search-params.mdx (added, +318/-0)
  • docs/02-pages/04-api-reference/04-config/01-next-config-js/optimizePackageImports.mdx (modified, +1/-0)
  • errors/next-prerender-dynamic-metadata.mdx (modified, +4/-4)
  • errors/next-prerender-dynamic-viewport.mdx (modified, +4/-4)
  • lerna.json (modified, +3/-2)
  • packages/create-next-app/helpers/get-pkg-manager.ts (modified, +34/-0)
  • packages/create-next-app/package.json (modified, +1/-1)
  • packages/create-next-app/templates/index.ts (modified, +24/-18)
  • packages/eslint-config-next/package.json (modified, +2/-2)
  • packages/eslint-plugin-internal/package.json (modified, +1/-1)
  • packages/eslint-plugin-next/package.json (modified, +1/-1)
  • packages/font/package.json (modified, +1/-1)
  • packages/next-bundle-analyzer/package.json (modified, +1/-1)
  • packages/next-codemod/package.json (modified, +1/-1)
  • packages/next-env/package.json (modified, +1/-1)
  • packages/next-mdx/package.json (modified, +1/-1)
  • packages/next-plugin-storybook/package.json (modified, +1/-1)
  • packages/next-polyfill-module/package.json (modified, +1/-1)
  • packages/next-polyfill-nomodule/package.json (modified, +1/-1)
  • packages/next-rspack/package.json (modified, +1/-1)
  • packages/next-swc/package.json (modified, +1/-1)
  • packages/next/errors.json (modified, +3/-1)
  • packages/next/package.json (modified, +7/-7)
  • packages/next/src/build/index.ts (modified, +6/-2)
  • packages/next/src/build/templates/app-page.ts (modified, +4/-0)
  • packages/next/src/build/templates/edge-ssr-app.ts (modified, +4/-0)
  • packages/next/src/build/utils.ts (modified, +23/-3)
  • packages/next/src/client/components/segment-cache/lru.ts (modified, +2/-0)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.development.js (modified, +129/-110)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.browser.production.js (modified, +67/-55)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.edge.development.js (modified, +127/-108)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.edge.production.js (modified, +67/-55)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.node.development.js (modified, +127/-108)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-client.node.production.js (modified, +67/-55)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-server.browser.development.js (modified, +603/-342)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-server.browser.production.js (modified, +578/-307)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-server.edge.development.js (modified, +606/-343)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-server.edge.production.js (modified, +581/-308)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-server.node.development.js (modified, +612/-347)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/cjs/react-server-dom-turbopack-server.node.production.js (modified, +587/-312)
  • packages/next/src/compiled/react-server-dom-turbopack-experimental/package.json (modified, +2/-2)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js (modified, +129/-110)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js (modified, +67/-55)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js (modified, +127/-108)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js (modified, +67/-55)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js (modified, +127/-108)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js (modified, +67/-55)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.development.js (modified, +603/-342)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.browser.production.js (modified, +578/-307)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.development.js (modified, +606/-343)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.edge.production.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.development.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-turbopack/cjs/react-server-dom-turbopack-server.node.production.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-turbopack/package.json (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.development.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.browser.production.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.edge.development.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.edge.production.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.node.development.js (modified, +0/-0)
  • packages/next/src/compiled/react-server-dom-webpack-experimental/cjs/react-server-dom-webpack-client.node.production.js (modified, +0/-0)

Code Example

- Platform: Linux
- Node: v22.16.0
- Next.js: 16.0.10
- output: standalone
- Router: App Router
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/austin-raey/next-memory-issue

To Reproduce

  1. Create a Next.js app with output: 'standalone'
  2. Make fetch requests to an external API
  3. With just 2 requests per second, OOM occurs after a few minutes

Current vs. Expected behavior

  • Current: Memory continuously grows until OOM after ~2 requests/second. GC cannot release the memory.
  • Expected: Memory should stabilize, GC should work properly, no OOM.

Provide environment information

- Platform: Linux
- Node: v22.16.0
- Next.js: 16.0.10
- output: standalone
- Router: App Router

Which area(s) are affected? (Select all that apply)

Performance

Which stage(s) are affected? (Select all that apply)

Other (Deployed)

Additional context

Related to PR #88577 (fix for issue #85914). The fix should properly cancel both branches of a tee'd ReadableStream, but the issue still persists in 16.0.10.

@icyJoseph I've tested with [email protected] (which should include the fix from #88577), but the memory leak still occurs.

Heap Timeline Analysis The heap timeline shows that string and object types are being retained and continuously accumulated. These objects are referenced by cacheController

nextjs-memory-leak.heaptimeline.zip

extent analysis

Fix Summary

The leak is caused by un‑cancelled ReadableStream branches created by Next’s internal cacheController.
The practical fix is to ensure every fetch response body is fully consumed or explicitly cancelled, and to upgrade to a version of Next that contains the corrected cacheController (≥ 16.2.1). If you must stay on 16.0.10, patch the file locally.


Step‑by‑Step Fix Plan

1️⃣ Upgrade Next (preferred)

# In your project root
npm i next@latest   # currently 16.2.1 or newer
# or, if you need the exact canary that contains the fix
npm i [email protected]

Re‑build the standalone bundle:

npm run build && npm run start

The fix in PR #88577 was merged after 16.0.10;

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - ✅(Solved) Fix Memory leak causing OOM still occurs in Next.js 16.0.10 (also tested with 16.0.1) when using output: standalone with fetch requests. [1 pull requests, 18 comments, 6 participants]