The Error

Your build or Node.js server crashes with:

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

or

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

Node.js (via the V8 engine) limits how much memory JavaScript objects can use. When your program needs more than that limit and garbage collection can't free enough, Node crashes. It usually means one of two things: the job genuinely needs more memory (big builds), or something is leaking memory (servers that crash after running for a while).


๐ŸŽฏ Quick Fix (Builds)

Give Node more heap, in megabytes:

# macOS / Linux
NODE_OPTIONS="--max-old-space-size=4096" npm run build

# Windows PowerShell
$env:NODE_OPTIONS="--max-old-space-size=4096"; npm run build

Or in package.json:

{
  "scripts": {
    "build": "NODE_OPTIONS=--max-old-space-size=4096 next build"
  }
}

Set it below the machine's actual RAM (leave room for the OS and other processes). On a 4 GB CI runner, try 3072.


Which Situation Are You In?

flowchart TD Q{"When does it crash?"} -->|"During build / bundling"| B["Big build: raise heap,
reduce build work"] Q -->|"Server crashes after
hours or days"| L["Likely a memory leak:
profile and fix"] Q -->|"Processing a big file
or dataset"| S["Loading too much at once:
stream or batch it"] Q -->|"In a container / CI"| C["Heap vs container limit:
set heap below memory limit"]

Fix 1: Big Builds (Next.js, Webpack, TypeScript)

  • Raise the heap with --max-old-space-size
  • Upgrade Node.js and your framework; newer versions often use less memory
  • Turn off source maps in production builds if you don't need them
  • For TypeScript monorepos, use project references and incremental builds
  • On CI, use a runner with more RAM rather than squeezing a huge build into 2 GB

Fix 2: Memory Leaks in Servers

Watch out: raising the heap limit on a leaking server only delays the crash. If memory keeps climbing over time, find the leak.

Common leaks:

Leak Example Fix
Unbounded cache const cache = {} that only grows Use an LRU cache with a size limit
Global arrays Pushing every request into a module-level array Don't store per-request data globally
Event listeners Adding a listener per request, never removing Remove listeners; use once
Timers setInterval never cleared clearInterval on cleanup
Closures holding big objects Callbacks keeping large data alive Release references when done

Find it with a heap snapshot:

node --inspect server.js
# open chrome://inspect โ†’ Memory โ†’ take heap snapshots
# take one, apply load, take another, compare what grew

Or write snapshots on demand:

import v8 from "node:v8";
process.on("SIGUSR2", () => console.log(v8.writeHeapSnapshot()));

Compare two snapshots in Chrome DevTools and look for object types whose count keeps growing.


Fix 3: Processing Large Data

// โŒ loads the whole 3 GB file into memory
const data = JSON.parse(fs.readFileSync("huge.json", "utf8"));

// โœ… stream line by line
import readline from "node:readline";
const rl = readline.createInterface({ input: fs.createReadStream("huge.ndjson") });
for await (const line of rl) {
  process(JSON.parse(line));
}

The same applies to databases: paginate or stream query results instead of fetching millions of rows at once.


Fix 4: Containers and Serverless

Node sets its default heap limit based on available memory, but in containers you should be explicit. Set --max-old-space-size to roughly 75% of the container's memory limit, so the container isn't killed by the system (OOMKilled) before Node can garbage-collect.


Monitor Memory

setInterval(() => {
  const { heapUsed, rss } = process.memoryUsage();
  console.log(`heap ${Math.round(heapUsed / 1e6)} MB, rss ${Math.round(rss / 1e6)} MB`);
}, 30_000);

If heap usage climbs steadily and never comes back down after load drops, you have a leak.


Frequently Asked Questions

How do I increase Node.js memory limit?

Set the --max-old-space-size flag in megabytes, for example NODE_OPTIONS="--max-old-space-size=4096" before your command. Keep the value below the machine's or container's available memory so the operating system doesn't kill the process.

Why does my Next.js build run out of memory?

Large projects, many pages, source maps and type checking can exceed Node's default heap, especially on CI runners with limited RAM. Increase the heap size, upgrade Node and Next.js, disable unneeded production source maps, or use a larger build machine.

How do I find a memory leak in Node.js?

Run Node with --inspect, open Chrome DevTools via chrome://inspect, and take heap snapshots before and after applying load. Compare them to see which objects keep growing. Common culprits are unbounded caches, global arrays, uncleared timers and leftover event listeners.


Conclusion

"JavaScript heap out of memory" means Node hit its memory limit. For big builds, raise --max-old-space-size within your machine's RAM. For servers that crash over time, find and fix the leak with heap snapshots. For large data, stream instead of loading everything at once.


Sources

Last verified: 2 November 2026.


Related reads: Fix Next.js Hydration Error ยท Fix Postgres Too Many Connections ยท Fix Docker Permission Denied

I write practical guides for developers. Follow on LinkedIn or X, or invite me to speak.