nextjs - ✅(Solved) Fix Memory Leak with node 22 (also 20, 24) + fetch + Next 16.0.1 + `output: standalone` [2 pull requests, 25 comments, 13 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#85914Fetched 2026-04-08 02:13:24
View on GitHub
Comments
25
Participants
13
Timeline
105
Reactions
35

Root Cause

  • I have seen other tickets make note of this and were able to fix it with a specific version of node, although unfortunately this made no difference for me. I have tried using other of the latest LTS versions of node (20, 22, 24 at the time of writing 24.11.0, 22.21.1, 20.19.5) and it seems this issue still persists on each of these versions. You can easily try different node versions by modifying the first line of the Dockerfile.
  • I've also observed this issue on the latest version of Next 15 (15.5.6 at the time of writing).
  • Using axios instead of fetch (which I believe doesn't use undici) seems to help with this issue. Of course, this is not ideal, because Next provides nice additions to fetch for caching.

Fix Action

Fixed

PR fix notes

PR #1307: fix(deps): update nextjs monorepo to v16.0.2 (patch)

Description (problem / solution / changelog)

This PR contains the following updates:


Release Notes

<details> <summary>vercel/next.js (@&#8203;next/third-parties)</summary>

v16.0.2

Compare Source

</details> <details> <summary>vercel/next.js (eslint-config-next)</summary>

v16.0.2

Compare Source

</details> <details> <summary>vercel/next.js (next)</summary>

v16.0.2

Compare Source

</details>

Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • <!-- rebase-check -->If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Changed files

  • package.json (modified, +3/-3)
  • pnpm-lock.yaml (modified, +56/-56)

PR #88577: Add 2nd cloned body to FinalizationRegistry. Only used RuntimeStyles component for webpack

Description (problem / solution / changelog)

What?

Reduces memory retention in two areas: response stream cleanup in cloneResponse and unnecessary runtime style initialization in Turbopack mode. Also adds a test fixture for standalone mode fetch memory leak detection.

Why?

Based on the reproduction provided in #85914, investigating potential sources of memory retention. When a ReadableStream is tee'd, both branches must be cancelled to release connection resources — previously only one branch was registered for GC cancellation. Additionally, RuntimeStyles and _N_E_STYLE_LOAD were always initialized even in Turbopack mode where they are unused.

How?

clone-response.ts: Register both cloned1 and cloned2 bodies with the FinalizationRegistry so that when either response is garbage collected, its stream branch is properly cancelled.

app-router.tsx: Guard _N_E_STYLE_LOAD and style tracking Set initialization behind !process.env.TURBOPACK && typeof window !== 'undefined'. Rename the component to RuntimeStylesForWebpack and skip rendering it entirely when using Turbopack.

Fixes #85914

Changed files

  • packages/next/src/client/components/app-router.tsx (modified, +21/-15)
  • packages/next/src/server/lib/clone-response.ts (modified, +18/-18)

Code Example

Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:34:05 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T6041
  Available memory (MB): 49152
  Available CPU cores: 14
Binaries:
  Node: 25.1.0
  npm: 11.6.2
  Yarn: N/A
  pnpm: 10.20.0
Relevant Packages:
  next: 16.0.1 // Latest available version is detected (16.0.1).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: standalone
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

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

To Reproduce

  1. Run pnpm install
  2. In src/app/page.tsx, replace "http://put-large-api-json-request-here.test" with some JSON endpoint. I didn't want to put someone's URL here as to not DDOS them haha. Preferably one where you are not rate limited. You can probably separately set up a seperate folder with an express (or similar) API endpoint that returns a large JSON payload as to not DOS anyone. As to not pollute the test, it may be best for you to not make this JSON endpoint in this example Next repo itself (this may not make a difference though tbf)
  3. With Docker Desktop, Rancher Desktop, or etc running, do make run.
  4. Open an Inspector session in Chrome / Edge / etc. (about:inspect in Chromium browsers) 4a. Optionally, go to the http://localhost:3000 page in your browser once, reload the page a few (2 or 3) times, then click "Collect garbage" a few times to ensure a clean heap, then "Take snapshot" of the heap to collect a baseline.
<details><summary>Image of the "Collect Garbage" button in Chromium browsers</summary>

Image

</details>
  1. In a seperate terminal tab in the example repository, run pnpm exec autocannon -R 30 -f http://localhost:3000. Let this run for a few minutes or so. -R 30 may be adjusted for more requests, but 30 is probably fine.
  2. After waiting, hit CTRL + C to stop autocannon.
  3. Go to the Inspector. Before taking the heap snapshot, click the "Collect garbage" broom icon to ensure the heap is clean. Note the heap is now larger than baseline and collecting garbage will not reduce this size.
  4. Inspecting the heap, it seems a large portion is now taken up by fetch. There is also Array and InternalReadableByteStream which seems suspicious, but I am not sure if they are relevant:
<details><summary>Image of the suspicious items in heap</summary>

Image

Image

</details>

Current vs. Expected behavior

I would expect the heap, once garbaged collected, to be similar in size to the baseline heap. Instead, the heap size is now permanently larger and it seems a large portion is taken up by fetch.

This larger size is sticky and I haven't seen it ever go back down even after waiting several minutes with no requests made to http://localhost:3000. Manual garbage collection makes no change either.

Provide environment information

Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0: Mon Oct 20 19:34:05 PDT 2025; root:xnu-12377.41.6~2/RELEASE_ARM64_T6041
  Available memory (MB): 49152
  Available CPU cores: 14
Binaries:
  Node: 25.1.0
  npm: 11.6.2
  Yarn: N/A
  pnpm: 10.20.0
Relevant Packages:
  next: 16.0.1 // Latest available version is detected (16.0.1).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
  output: standalone

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

Not sure, Runtime

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

Other (Deployed)

Additional context

  • I have seen other tickets make note of this and were able to fix it with a specific version of node, although unfortunately this made no difference for me. I have tried using other of the latest LTS versions of node (20, 22, 24 at the time of writing 24.11.0, 22.21.1, 20.19.5) and it seems this issue still persists on each of these versions. You can easily try different node versions by modifying the first line of the Dockerfile.
  • I've also observed this issue on the latest version of Next 15 (15.5.6 at the time of writing).
  • Using axios instead of fetch (which I believe doesn't use undici) seems to help with this issue. Of course, this is not ideal, because Next provides nice additions to fetch for caching.

extent analysis

TL;DR

The issue can be mitigated by using a different HTTP client library, such as axios, instead of the built-in fetch function, which seems to be causing the memory leak.

Guidance

  • Try replacing fetch with axios in the code to see if it resolves the memory leak issue.
  • Investigate the undici library, which is used by fetch in Node.js, to see if there are any known issues or updates that could address the memory leak.
  • Consider updating to a newer version of Node.js or Next.js to see if the issue is resolved in later versions.
  • Use the Chrome Inspector to monitor the heap size and garbage collection after making changes to the code to verify if the issue is resolved.

Example

No specific code example is provided, but replacing fetch with axios could look like this:

import axios from 'axios';

// Replace fetch with axios
axios.get('http://example.com/api/data')
  .then(response => {
    // Handle response data
  })
  .catch(error => {
    // Handle error
  });

Notes

The issue seems to be related to the fetch function and the undici library, but the exact cause is unclear. Using axios instead of fetch may help mitigate the issue, but it's not a ideal solution since Next.js provides additional features for caching with fetch.

Recommendation

Apply workaround by using axios instead of fetch, as it seems to resolve the memory leak issue. This is a temporary solution until the root cause of the issue is identified and fixed.

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 with node 22 (also 20, 24) + fetch + Next 16.0.1 + `output: standalone` [2 pull requests, 25 comments, 13 participants]