'JavaScript heap out of memory' — how to fix it
Quick answer: FATAL ERROR: ... JavaScript heap out of memory means Node's V8 heap hit its ceiling. For a big build, raise it with NODE_OPTIONS=--max-old-space-size=4096 (MB). But if memory grows forever in a running service, that's a leak — raising the limit only delays the crash; profile the heap and fix what keeps growing instead.
What the error looks like
It's a hard crash with a V8 stack, not a catchable exception:
<--- Last few GCs --->
FATAL ERROR: Reached heap limit Allocation failed -
JavaScript heap out of memory
1: 0xb09... node::Abort()
2: 0xc0f... v8::internal::Heap::FatalProcessOutOfMemory()
Two very different situations share this message: a one-off build that needs more memory than the default, and a long-running service that leaks until it dies. The fix is different for each.
Why it happens
A big build hits the default ceiling
Webpack, tsc, or a large bundle needs more than Node's default heap for that one task.
A real memory leak
A growing cache, unbounded array, or retained closures climb until the heap is exhausted.
Loading too much at once
Reading a huge file or query result fully into memory instead of streaming it.
An old default limit
Older Node defaults to roughly a 2 GB old-space, which large workloads outgrow.
Diagnose it in three steps
Build or runtime?
# Crashes during 'npm run build' -> build needs more heap.
# Crashes after hours of serving traffic -> suspect a leak.Does it grow without bound?
node --inspect server.js # take heap snapshots over time in DevTools
# Steadily rising retained size between snapshots = leak.Raise it for the build (only)
NODE_OPTIONS=--max-old-space-size=4096 npm run buildRaise it for builds, profile it for services
A build is a fine place to grant more memory — it runs once and exits. A long-running service is not: more heap just means it takes longer to fall over.
- Builds: set
--max-old-space-sizeto fit your CI box and move on. - Services: capture a heap snapshot under load, find the retained objects, and stream large data instead of buffering it.
- Containers: keep the heap flag below the container memory limit so you don't just trade this crash for an
OOMKilled137.
Keep the service up while you find the leak
Infraveil doesn't rewrite your code, but it keeps a leaky service survivable on your own servers: the agent restarts the process when it dies, shows the crash in one place, and lets you roll back to a healthier build — buying you time to profile and fix the real cause instead of firefighting in production.
Frequently asked questions
How do I fix 'JavaScript heap out of memory'?
For a build, raise the limit with NODE_OPTIONS=--max-old-space-size=4096. For a running service that keeps growing, profile the heap and fix the leak — raising the limit only delays the crash.
What does --max-old-space-size do?
It sets the maximum size (in MB) of V8's old-space heap. Raising it lets memory-heavy tasks complete, but it can't fix code that leaks without bound.
Why does my build run out of memory?
Bundlers and TypeScript can need more memory than Node's default heap for large projects. Grant more for the build step specifically.
Is heap-out-of-memory the same as OOMKilled (137)?
No. Heap-out-of-memory is V8 hitting its own configured ceiling. OOMKilled (exit 137) is the OS/container killing the process for exceeding the container's memory limit. They can chain — set the heap flag below the container limit.