Memory leak with axios and AbortSignal in middleware in next >=15.4
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 142k
- Forks
- 32.4k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 351
Description
Link to the code that reproduces this issue
https://github.com/liammcateer/next-abort-signal-memory-leak-reproduction
To Reproduce
- Run
npm install - Build the next app:
npm run build - Run the mock server in a separate terminal window:
node mockServer.js - Start the next app:
npm run start - Make many requests (I do 1,000) to a single page
- Take a heap snapshot using
kill -USR2 <next-server PID>. You can find thePIDby runningps aux | grep "next-server (v15.5.5)" - Open the heap snapshot in chrome dev tools and look for increasing memory
- Repeat steps 5-7 with all other pages.
You will notice that /middleware/axios is the only one that increases memory. You can also verify this by leaving the server running for a little bit and noticing that the memory is never returned.
Current vs. Expected behavior
I expect that fetching an API with axios using the AbortSignal should not cause a memory leak.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 24.3.0: Thu Jan 2 20:24:16 PST 2025; root:xnu-11215.81.4~3/RELEASE_ARM64_T6000
Available memory (MB): 32768
Available CPU cores: 8
Binaries:
Node: 22.14.0
npm: 10.9.2
Yarn: 1.22.22
pnpm: N/A
Relevant Packages:
next: 15.5.5 // No Next.js version data was found.
eslint-config-next: 15.5.5
react: 19.1.0
react-dom: 19.1.0
typescript: 5.9.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Middleware
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
Tested against different canary releases, the first one that introduced the issue is 15.4.0-canary.95. 15.4.0-canary.94 does not have the issue.
When using axios to call an API inside middlware.ts with an AbortSignal, a memory leak appears.
This code will reproduce the issue:
export async function middleware(req: NextRequest) {
await axios.get('https://<some-api>/', {
signal: AbortSignal.timeout(1000),
adapter: 'fetch',
});
return NextResponse.next();
}
If the AbortSignal is removed, or fetch is used instead of axios with an AbortSignal, the issue goes away.
In my reproduction, I called the same api using fetch and axios in both middleware.ts and page.tsx. The issue is only present when axios is used in middleware.ts. Each request was made 1000 times.
Here is a screenshot of various heap snapshots taken after each test. You can see that when axios is used in middleware, the problem presents. I also took another snapshot 30 seconds later, and the memory was still not released. I have also taken some snapshots (not shown) where I left the app for 15 mins, and the memory was still not released.
This screenshot shows quite a few (over 2000) {signal,abort} objects hanging around
I understand that calling APIs in middleware is an anti-pattern, however, this used to work previously, so should be reported as a bug. I also understand that there is a workaround to use fetch instead of axios. Our generated API fetching code uses axios, so our team would need to spend some effort to migrate away from axios. We are using axios with the fetch adapter.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked reproduction and its middleware.ts, running the documented npm install, build, mockServer.js, and start commands. Compare the behavior between 15.4.0-canary.94 and 15.4.0-canary.95, then repeat the heap-snapshot procedure for the axios fetch adapter and AbortSignal case. Done means repeated middleware requests no longer retain the growing signal objects or unreleased memory.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nextjs, node.js, typescript
- Domain
- backend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100