prisma: Prisma Memory Leak when using in NestJS app, reported by Jest
Bug description
In our (closed source) project, we added a lot of test for a new feature. That resulted in memory problems in our ci.
We found, that Prisma is might be one of the problems. I created a minimal reproduction https://github.com/adrian-goe/prisma-nestjs-memory-leak-repoduction
There is one test without using prisma app.controller.spec.ts and one using prisma app-prisma.controller.spec.ts
running both test with node --expose-gc
and jest --detectLeaks
results in jest finding memory leaks in the test with prisma.
It might be possible, that this leaks also happens while running the application, but I didn’t test that.
It could be possible, that this is a nestJs problem as well, but we ware only be able to reproduce this with Prisma, but no other dependency or module.
How to reproduce
https://github.com/adrian-goe/prisma-nestjs-memory-leak-repoduction
Expected behavior
No response
Prisma information
see https://github.com/adrian-goe/prisma-nestjs-memory-leak-repoduction
Environment & setup
- OS: [macOS, Windows, Debian] might be more
- Database: [PostgreSQL] only tested with postgres
- Node.js version: v16.18.0
Prisma Version
prisma : 4.10.1
@prisma/client : 4.10.1
Current platform : darwin-arm64
Query Engine (Node-API) : libquery-engine aead147aa326ccb985dcfed5b065b4fdabd44b19 (at node_modules/@prisma/engines/libquery_engine-darwin-arm64.dylib.node)
Migration Engine : migration-engine-cli aead147aa326ccb985dcfed5b065b4fdabd44b19 (at node_modules/@prisma/engines/migration-engine-darwin-arm64)
Format Wasm : @prisma/prisma-fmt-wasm 4.10.1-1.80b351cc7c06d352abe81be19b8a89e9c6b7c110
Default Engines Hash : aead147aa326ccb985dcfed5b065b4fdabd44b19
Studio : 0.481.0
In our internal project, this was also an issue with Prisma 4.1.1
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 4
- Comments: 59 (15 by maintainers)
Our team ran into a similar issue with our NestJS application. The memory leak is very slow (about 800MB in 48 hours). Approximate server load information:
We tried several options to localize the memory leak. Here is the result we got. When running the application with
engineType "library"
nodeJS process keep on consume memory. When usingengineType "binary"
nodeJS application uses memory correctly but the prisma-query-engine process continues to consume memory. When comparing 2 different launch methods,engineType "library"
leaks about twice as fast compared toengineType "binary"
. We are using prisma version 5.2.0, node v16.18.1.OS info: Linux 5.4.179-1.el8.elrepo.x86_64 #1 SMP Thu Feb 10 10:14:12 EST 2022 x86_64 x86_64 x86_64 GNU/Linux
Memory usage:
Prisma info:
Memory usage chart (
engineType "binary"
)I can confirm there is some memory leak in the Prisma query engine. It affects all our apps which use Prisma and make a lot of DB calls regardless of whether they are read-only apps or the ones fetching external data and storing it to the DB.
I thought Prisma 5 might solve this problem but after I updated the dependencies today, I can see the issue is still there.
The memory used by our apps slowly grows day-by-day until they eventually run out of memory and their containers are restarted.
Below I show some examples what this problem looks like in both library and binary mode. In these cases, I simply hit some of our API endpoints that make really heavy DB calls so I can reproduce the issue more quickly.
Library
When we use
library
engine type, the issue is only visible as the difference betweenrss
memory usage.You can clearly see there’s no memory leak in our app or in Prisma client because the heap size remains stable.
Before Heavy Load
After Heavy Load
Binary
When we use
binary
engine type, it is clearly visible that the query engine uses a lot of memory.Used memory is shown as percentage below. But it’s easy to calculate how much memory those processes use since the machine where the app runs has 1GB RAM.
I only made a single set of heavy DB calls. But I can repeat this over and over again with the very same calls and I always end up with more and more memory used by the query engine.
After Start
After I start the application, the Node.js memory usage looks like this:
…and relevant system processes like this:
After Heat Up Period
I let the application run for a while but there’s nothing going on except for regular health checks (which also connect to the DB).
After Heavy Load
After Cool Down Period
When I wait for a while after the heavy DB calls, I can see that GC kicks in and cleans up the heap. However, the memory used by the Prisma query engine doesn’t go down.
Can confirm: Upgrading to Node v20 and Prisma v5.5.2 fixed the leak for me. Previously, memory usage would increase to 2GB within a few hours. Now, it remains at approximately 600MB over the same time span.
Same here, my issues have been resolved since the node upgrade. 5.5.2 & Node 18.18.2 Thanks to whoever fixed it, accidentally or on purpose!
In case folks missed it, this looks like its related to using Prisma on Node 16/18. Updating to Nodejs v20 fixed the memory leak for my team.
I’m sorry I know this is not a particularly helpful comment, but we’re definitely getting the same issues as described above in production too.
For now we’re also restarting everything regularly with pm2.
Can’t share too much other info about our setup on here, but if someone from prisma wants to reach out I can spare some time.
So I can confirm that the reproduction outputs the following message:
I also sent a PR to make the reproduction actually work out of the box: https://github.com/adrian-goe/prisma-nestjs-memory-leak-repoduction/pull/1
Note: Even though this is now on
confirmed
, it does not mean there has to be a problem at Prisma. We will keep investigating that.Same - had a few weeks without issue since the upgrade, seems to be fixed!
I believe that we are also experiencing this - I can’t give source code publicly, but I am happy to add a few developers to our repo for research purposes if that helps. Nest.js - Node 18 - Prisma, deployed on Heroku, crashes out with heap allocation about once per day.
I wrote a very simple sample app and left it running over the weekend and I believe it repros the issue. The code is here: https://github.com/whalesync-ryder/prisma-leak-demo
Here’s the memory over 27 hours:
Let me know if you have any questions, hope that helps! Edit: forgot to mention running on node v16.13.0. (which we need to upgrade from but you know)
Update somethings:
I use
prom-client
andgrafana
to monitor memory.Before Update:
After Update:
@mmmeff I tested it with the reproduction, i posted. That did not fix it.
Node: 20.6.1 Prisma: 5.2.0
@janpio I pushed it on a seperate branch https://github.com/adrian-goe/prisma-nestjs-memory-leak-repoduction/tree/node20
edit: here is a PR with a test pipline: https://github.com/adrian-goe/prisma-nestjs-memory-leak-repoduction/pull/3
can’t tell you guys how excited i am to have finally found others in my boat, this mem leak has been plaguing my highly used app in prod. my prod server crashes every 2 days due to a memory leak, goes over 95% then poof on its own if i dont keep an eye on it. i have to restart it nightly. i have a cronjob that restarts the
dota
docker container for me nightly, which uses the most prisma, but my other packages still use prisma so those are more slowly leaking too and i’ll have to restart the whole server eventually (like today it crashed in 3 days despite restartingdota
once a night)after adding new commits that depend more on db queries, it now shoots up from ~350mb-400mb before a restart in 2 days, to ~650mb in just a few hours (master branch) !
last known “working” version with 350mb-450mb rss usage over a few days (still needs restarted, it goes up to 600mb+ if left alone)
commits since then have created the memory leak within 3 hours to 650mb+. somewhere in here causes a big prisma memory leak i just haven’t inspected the commits to see what it is (i guessed the extra db calls)
reproduce: i can reproduce this locally every time using my unit tests, you can too if you clone & run the prisma seeder. feel free to add me as friend on discord #techleed if you need help setting up
linkback to what i thought was the issue (overusing global variables), but now can see it’s prisma
i use prisma 5.2.0
this is the package that crashes
here’s the prisma schema, i use both mongo and psql
prod runs on
my local repro ran on (M1 Max)
Sounds like the next thing I need to try is prisma 4.8.1
(no sensitive data here, just seed data)
This issue is keeping us from upgrading past 4.8, since our containers die after around a day. There’s lots of features in 5.0 i’m looking on with envy until this gets resolved.
It’s worth noting that the existing memory leak tests will not detect this issue because they’re examining only the NodeJS heap size; it’s likely that the existing test suite could be adjusted to catch this class of issue by using
process.memoryUsage().rss
to capture total memory usage, rather thanheapUsed
here: https://github.com/prisma/prisma/blob/main/packages/client/tests/memory/_utils/createMemoryTest.ts#L63I’ve created a new issue where there’s a reproduction with no other dependency but Prisma.
Technically I cannot call it a memory leak but I am for sure calling it a memory mismanagement.
My feeling is that the following commit is causing it: https://github.com/prisma/prisma/commit/f395abad8eb85739a1df35071caa9e5050993696 but that’s just a feeling since I know the prisma infrastructure is super complex and I’m not a Rust developer.
I hope it helps in your investigation.
Hey @livthomas we’ll need further information to be able to help you at all. Ideally, a minimal reproduction repro of the issue would be best (schema, js/ts code, query data). It would be greatly beneficial if you could share what exactly is going wrong, specific error messages, specific outcomes you’re running into, and if possible, any graphs / data that indicate a memory leak (or high memory usage). Here’s an example of what I mean per graphs / data for profiling such issues.
I am in the process of upgrading my node right now, so i should be able to confirm pretty soon if that resolved it for me. Thanks for the info.
@whalesync-ryder I could reproduce finally using Node.js v16, the reproduction in GitHub Actions was missing
yarn prisma db push
at first, so previous reproductions were actually not executing any queries, they were all failing because the database didn’t exist.Did you upgrade to v18 or v20 already? This problem looks only related to Node.js v16 (which is “end of life”) to me at the moment, see results:
Note:
--max-old-space-size
to show howrss
is actually reclaimed and growingrss
is not a problem in itself, as long as it’s reclaimed when there is some memory pressure.Using
nest start
Upgrade all + Prisma 5.5.2 + --max-old-space-size=150 - Node v16.20.2 https://docs.google.com/spreadsheets/d/14-9DFfkW_DD_dAdj3WTsQ4kTm_HONd0fgE1rgUgGljo/edit?usp=sharing 🔴 There is definitely a leak here!
Upgrade all + Prisma 5.5.2 + --max-old-space-size=150 - Node v18.18.2 Actually ran out of memory at
nest start
, see next section for resultsUpgrade all + Prisma 5.5.2 + --max-old-space-size=150 - Node v20.9.0 https://docs.google.com/spreadsheets/d/1eSGaXS34aMqWJUW9r-oFjX5IU8ojQ5lAhSHHMsRJzQ4/edit?usp=sharing
Using
yarn run build
and thennode dist/main
Notes:
nest start
appears to consume a lot of memory when starting, so I switched to building and starting the server with Node.js instead.Upgrade all + Prisma 5.5.2 + --max-old-space-size=150 + node dist/main - Node v16.20.2 https://docs.google.com/spreadsheets/d/1BQJLIMGl3xCQSFMNfYUgzdcAUhxaxHc8JnZqlFWJJJg/edit?usp=sharing 🔴 There is definitely a leak here!
Upgrade all + Prisma 5.5.2 + --max-old-space-size=150 + node dist/main - Node v18.18.2 https://docs.google.com/spreadsheets/d/1rDRyzjWi15ZC4az2-Hz0mULcskx98xfQ8ODoAYkGV7E/edit?usp=sharing
Upgrade all + Prisma 5.5.2 + --max-old-space-size=150 + node dist/main - Node v20.9.0 https://docs.google.com/spreadsheets/d/16hOzvpRsdtt3eay8xejz3ukTFByjPkm0t_6d1d_cFoY/edit?usp=sharing
I needed to run a script to import around 12 million records.
Runing this query on Prisma 5.4.1 and NodeJS 18.12.0 was causing a memory leak. A simple script running only this query would consume all server memory and crash. Optimizing it with
$queryRaw
didn’t help. Then I tried calling the raw query with pg 8.11.3 on Nodejs 18.12.0 and got normal memory consumption so the problem was with Prisma 5.4.1 on NodeJS 18.12.0. I upgraded to NodeJS 20.8.0 and tested the originalfindUnique
on Prisma 5.4.1 - this solved the problem. The server is running Debian GNU/Linux 10 (buster), but the same thing was happening on Mac OS X.@janpio Very interesting! So you’re not seeing any difference. Maybe I had something else going on to explain the 10x difference in leak speed between my two runs. I can’t imagine what it would be.
@janpio I can try, will use the same setup from the main instance. we are currently using
engineType = "library"
onnode:18.16-bullseye-slim
, so not an ARM64 issue (as opposed to the other thread #18510). we enabled the pprof profiler on some % of the instances to see who the culprit is and so far seems to be prismasame here, it’s a slow memory leak, and we’re restarting the containers after it crosses the 95% memory usage. it grows regardless of how much traffic the server is getting. all replicas eventually get OOM’d in a couple of hours (8-12 hours)
Just to give you an idea what this memory leak look like in another app when we keep it running for a day:
This app is a job executor that works all the time without any break since there are always more jobs than it can process. And the Node.js app itself still consumes just 196 MB of RAM while Prisma query engine consumes 513 MB which is constantly growing until the container eventually runs out of memory and is restarted.
for now I think using JavaScript only client and engine is the solution,
or move to Prisma for Schema + Kysely for data fetch and migration because Prisma not good enough
We’re also seeing a very clear memory leak in prisma, staring somewhere between version 4.3.1 and 4.12.0. The amount of leaked memory seems to depend on the amount of queries made with prisma, with some of our high-load services running out of memory in a day or two.
Hmm, we have same issue, it was working fine, but I don’t know what break