### Version v25.6.1 ### Platform ```text Darwin XXX 25.3.0 Darwin Kernel Version 25.3.0: Wed Jan 28 20:48:41 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6041 arm64 ``` ### Subsystem http ### What steps will reproduce the bug? When an HTTP request is executed, data in AsyncLocalStorage isn't freed. To reproduce it: ``` import hooks from 'node:async_hooks'; import http from 'node:http'; import net from 'node:net'; import crypto from 'node:crypto'; // http.setMaxIdleHTTPParsers(1); const store = new hooks.AsyncLocalStorage(); function sendRequest() { store.enterWith({body: crypto.randomBytes(512)}); const proxyReq = http.request({ agent: null, createConnection: net.createConnection, method: 'HEAD', hostname: '127.0.0.1', headers: { 'connection': 'close' }, port: 9009, path: '/', }); proxyReq.end(); } for (let i = 0; i < 10; i++) { for (let j = 0; j < 100; j++) { sendRequest(); } } setTimeout(() => { console.log('done'); }, 1000 * 60 * 60); ``` When running this with `node --inspect`, one can see that there are 1000 `AsyncContextFrame` entries in memory, as well as the buffer stored in the `AsyncLocalStorage`. This happens with `AsyncContextFrame` enabled (Node 24+) I stumbled upon this when making an outbound request from an HTTP server handler `(req, res) => {...}` where I was using AsyncLocalStorage to keep some request context. I noticed that the memory was freed if I made the outbound requests using `fetch()` instead of `http.request`. Also, if `http.setMaxIdleHTTPParsers(1);` is uncommented, so that HTTP parsers aren't reused, the memory is also freed. ### How often does it reproduce? Is there a required condition? Always ### What is the expected behavior? Why is that the expected behavior? Whatever is stored in an `AsyncLocalStorage` should be freed when it goes out of scope. ### What do you see instead? <img width="2123" height="1113" alt="Image" src="https://github.com/user-attachments/assets/970e8e75-8e8b-4d11-85cf-6633fa6a4543" /> It can be seen here that there are 1000 instances of `AsyncContextFrame` ### Additional information I downloaded Node's source and tinkered with the parser initialization in `_http_client.js` and with the AsyncWrap logic in `node_http_parser.cc`, but couldn't fix it. I see that `freeParser()` should free everything, but it seems something is being held. I'm not familiar with the relationship between `AsyncWrap` and V8-based new `AsyncLocalStorage` implementation. I understand that not reusing parsers has a memory impact. I also noticed PRs like https://github.com/nodejs/node/pull/57938 and https://github.com/nodejs/node/pull/59621 that might fix this thing. This is an issue when using libraries like Datadog's `dd-trace`, which store tracing information in `AsyncLocalStorage`