You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Significant heap usage regression in Node 22.19.0 #59733
Darwin ZG-F3FWLW4DJJ 24.6.0 Darwin Kernel Version 24.6.0: Mon Jul 14 11:28:30 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6030 arm64
Subsystem
No response
What steps will reproduce the bug?
Node 22.19.0 uses significantly more heap memory than 22.18.0. I think it's because of this change, which introduces a cache for package.json metadata. Some packages are structured in such a way that this cache ends up quite large. The reproduction provided here uses date-fns, which exhibits this clearly.
To reproduce, compare heap snapshots for a script like this:
In my testing, the total heap size for this script on 22.18 is ~7.2 MB, whereas on 22.19 it's ~28.9 MB. This was originally detected in a medium size application where an upgrade to 22.19 ballooned heap usage by more than 50 MB. Inspecting a heap snapshot shows that much of this increase is accounted for by objects retained by nearestParentPackageJSONCache
How often does it reproduce? Is there a required condition?
It reproduces consistently on 22.19.0
What is the expected behavior? Why is that the expected behavior?
I would not expect such a significant increase in heap usage
What do you see instead?
A significant increase in heap usage
Additional information
A zip containing heap snapshots for the reproduction script is attached
In case it's helpful for others: in our application at least, switching to date-fns single-function imports (e.g. import { isValid } from 'date-fns' -> import { isValid } from 'date-fns/isValid') reduced the magnitude of the heap increase significantly, so it does seem pretty package specific. That said, while this workaround works in this specific case, the size of this cache in memory still seems way too big.
I looked at the code how the original cache worked and how the new cache works and just by reading the code it seems to roughly contain the same data (now a nested object).
Could you check how much memory it used to use with Node.js 20? It was released in Node.js 21.5 and all 22 and onwards also contain the change with the C++ implementation.
@BridgeAR I think the big difference between the previous JS-side cache (the one removed in #50322) and the one introduced here is that the original cache was a map from package.json path to deserialized package.json metadata, whereas this is a map from any module file path to deserialized package.json metadata. This duplicates cache data when multiple module files share the same parent package.json file. This is obviously common in general, but there are also some degenerate cases like date-fns which have a ton of paths and a relatively large package.json metadata object
Just adding to the discussion, something has definitely changed in regards to memory between Node.JS 22.18 and 22.19. We have started seing 139 exit codes on the startup process of many applications and the increased heap usage mentioned. Downgrading to NodeJS 20 or 22.18 "fixes" the issue for us.
Reacted by João Guerra, uB4nshee, Alan Gomes, Jérémy Fauvel, Alex VrV, Konstantinos Tsanakas and Ronaldo Tafarel
Same in our team, we have seen an increase of 100MB across most of our apps.
A previous commentor mentioned date-fns, we definitely use that library and it might be responsible for the larger than average increase. Will report back if I manage to do some testing with and without.
Activity
nLeichtle commentedon Sep 3, 2025
I can confirm the behaviour. Memory consumption more than doubled.
Downgrading to 22.18 reduces back to "normal" memory size.
michaelsmithxyz commentedon Sep 3, 2025
In case it's helpful for others: in our application at least, switching to
date-fnssingle-function imports (e.g.import { isValid } from 'date-fns'->import { isValid } from 'date-fns/isValid') reduced the magnitude of the heap increase significantly, so it does seem pretty package specific. That said, while this workaround works in this specific case, the size of this cache in memory still seems way too big.BridgeAR commentedon Sep 8, 2025
I looked at the code how the original cache worked and how the new cache works and just by reading the code it seems to roughly contain the same data (now a nested object).
Could you check how much memory it used to use with Node.js 20? It was released in Node.js 21.5 and all 22 and onwards also contain the change with the C++ implementation.
michaelsmithxyz commentedon Sep 8, 2025
@BridgeAR Here are some data points for the reproduction in the original message:
michaelsmithxyz commentedon Sep 8, 2025
@BridgeAR I think the big difference between the previous JS-side cache (the one removed in #50322) and the one introduced here is that the original cache was a map from
package.jsonpath to deserializedpackage.jsonmetadata, whereas this is a map from any module file path to deserializedpackage.jsonmetadata. This duplicates cache data when multiple module files share the same parentpackage.jsonfile. This is obviously common in general, but there are also some degenerate cases likedate-fnswhich have a ton of paths and a relatively largepackage.jsonmetadata objectFelipeEmerim commentedon Sep 9, 2025
Just adding to the discussion, something has definitely changed in regards to memory between Node.JS 22.18 and 22.19. We have started seing 139 exit codes on the startup process of many applications and the increased heap usage mentioned. Downgrading to NodeJS 20 or 22.18 "fixes" the issue for us.
mqdeandrade commentedon Sep 10, 2025
Same in our team, we have seen an increase of 100MB across most of our apps.
A previous commentor mentioned date-fns, we definitely use that library and it might be responsible for the larger than average increase. Will report back if I manage to do some testing with and without.
BridgeAR commentedon Sep 12, 2025
@michaelsmithxyz that sounds right. Since you already looked into the issue, would you mind opening a PR to fix that?
Add 16-memory-leak-cache: reproduce the #1 leak (unbounded cache) + fix