payloadcms / payloadcms/payload
Excessive memory usage when using Payload CMS as a layout agnostic page builder
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Describe the Bug
My company's Next.js functions surpassed the maximum memory size of a Vercel function (4GB), so adding one more block to the config makes every single route error, preventing us from adding new functionality without removing existing functionality.
I performed a heap snapshot of the server and found that an overwhelming majority of the memory is coming from 219,801 instances of Mongoose's Schema class.
We have pnpm patched Payload to memoize the block schemas to get us back to manageable memory usage, but we'd like to see this fixed upstream if possible.
I am not as confident as I'd like to be in this fix outside of my own project at the moment since I am not as familiar with the inner workings of the DB adapter. I wanted to surface this for implementation by someone more familiar or for discussion before I tackle a fleshed out PR. Do you have thoughts on cache safety of these Schemas, or do you see an alternative root cause?
Reproduction
The reproduction is a contrived layout builder config which has a block tree that fans out wide.
This issue can be reproduced with any configuration with reused blocks and verified by Chrome DevTools attached to Node as well, the attached reproduction is mostly to show the explosive growth clearly.
Link to the code that reproduces this issue
Reproduction Steps
- Clone
evelynhathaway/payload@evelyn/block-schema-memory-repro - Install packages
- Run
node --expose-gc --import tsx test/_community/measure-schemas.ts
$ node --expose-gc --import tsx test/_community/measure-schemas.ts
================ Schema instance count ================
Total mongoose.Schema instances built by one init: 193,751
Schemas built per collection (live + _versions combined):
55,351 pages
27,677 sections
27,677 landingPages
27,677 marketingPages
27,677 campaigns
27,677 guides
5 media
2 users
2 menu
1 posts
1 payload-kv
1 payload-locked-documents
1 payload-preferences
1 payload-migrations
1 globals
================ Process memory ================
RSS: 2442.9 MiB
Heap total: 2279.2 MiB
Heap used: 1775.7 MiB
- Checkout
evelyn/block-schema-memory-potential-fixfor a potential fix (https://github.com/evelynhathaway/payload/commit/6920225c02870f5b7ac97e94d8e9ad801a6ef5e5) similar to our temporary workaround that caches the schemas - Run
node --expose-gc --import tsx test/_community/measure-schemas.ts
$ node --expose-gc --import tsx test/_community/measure-schemas.ts
================ Schema instance count ================
Total mongoose.Schema instances built by one init: 725
Schemas built per collection (live + _versions combined):
625 pages
17 sections
17 landingPages
17 marketingPages
17 campaigns
17 guides
5 media
2 users
2 menu
1 posts
1 payload-kv
1 payload-locked-documents
1 payload-preferences
1 payload-migrations
1 globals
================ Process memory ================
RSS: 358.9 MiB
Heap total: 247.8 MiB
Heap used: 83.0 MiB
Which area(s) are affected?
db: mongodb
Environment Info
Binaries:
Node: 24.14.0
npm: 11.9.0
Yarn: N/A
pnpm: 10.10.0
Relevant Packages:
payload: 3.85.0 (note this was also replicated in the repo against the main branch with package.json 4.0.0-beta.0, see git tree of repro)
Operating System:
Platform: linux
Arch: x64
Version: #58~22.04.1-Ubuntu SMP Thu May 7 22:16:53 UTC 2026
Available memory (MB): 31743
Available CPU cores: 8
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 reproduction at test/_community/config.ts and run test/_community/measure-schemas.ts using the documented Node command to establish the schema count and memory baseline. Compare the behavior with commit 6920225c02870f5b7ac97e94d8e9ad801a6ef5e5 and inspect how the database adapter builds schemas. Done means reused blocks no longer cause explosive Mongoose Schema growth while the reproduction remains functional.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- mongodb, nextjs, node.js, typescript
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100