RORK LABJP
TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the roundTOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Articles/Dev Tools
Dev Tools/2026-06-01Intermediate

Fixing 'JavaScript heap out of memory' in Metro and EAS Builds

Your Rork or Expo build dies with 'FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory.' Here is why it happens and exactly how to fix it, both locally and on EAS Build.

Metro4EAS Build14Memory4Expo149Troubleshooting38

I was building one of my wallpaper apps the other day when the bundle got almost ninety percent of the way through and the terminal suddenly went red: FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory. Restarting didn't help — it died at the same point every time. I run six wallpaper apps in parallel, and only the ones whose asset count had crept past a certain size ran into this.

The important thing to understand is that this error is not telling you your code is wrong. It is telling you that Node.js ran out of the memory it was given. Because the cause sits outside your source code, staring at the message alone rarely points you anywhere useful. Below I'll walk through where to make the fix — for both the local Metro bundler and EAS Build — so you can recover with the least friction.

Isolate the symptom and when it happens

There are three classic moments this error appears: during bundling with npx expo start, during an eas build cloud build right before the Gradle/Xcode stage while the bundle is generated, and while writing the production bundle with expo export.

What they share is a single moment where a large number of JavaScript modules get expanded at once. Node.js ships with a default heap ceiling (roughly 2GB to 4GB depending on version and environment), and a large app with many assets hits that ceiling first. In a sense, this error is proof that your app has grown.

Your first move is to confirm it really is a memory problem. Raise the ceiling temporarily before the build command, and if it passes, you have your answer.

# Temporarily raise the heap ceiling to 8GB and see if it still fails
NODE_OPTIONS=--max-old-space-size=8192 npx expo start --clear

If it stops dying, memory was the cause. If it still fails even with this, you need to suspect something else — a circular import or an infinite loop, for example.

Fix 1: Raise the local heap ceiling permanently

Typing the environment variable every time isn't realistic, so bake it into your package.json scripts. That keeps the behavior consistent across machines and teammates, and avoids forgotten flags.

{
  "scripts": {
    "start": "NODE_OPTIONS=--max-old-space-size=8192 expo start",
    "export": "NODE_OPTIONS=--max-old-space-size=8192 expo export"
  }
}

On Windows the NODE_OPTIONS=... prefix won't work, so wrap it with cross-env to make it portable across operating systems.

{
  "scripts": {
    "start": "cross-env NODE_OPTIONS=--max-old-space-size=8192 expo start"
  }
}

Use roughly half your installed RAM as the target. On a 16GB machine, 8192 (8GB) is a safe figure; pushing past your physical memory triggers swapping and actually slows things down. On my Mac it stabilized at 8192, and raising it further made no difference.

Fix 2: For EAS Build, raise the resource class

If the failure happens in the cloud build rather than locally, setting NODE_OPTIONS on your own machine does nothing. You need more memory on the EAS Build machine itself. Set resourceClass on each profile in eas.json.

{
  "build": {
    "production": {
      "android": { "resourceClass": "large" },
      "ios": { "resourceClass": "large" },
      "env": {
        "NODE_OPTIONS": "--max-old-space-size=8192"
      }
    }
  }
}

The key here is to raise the machine's memory with resourceClass while also lifting Node's heap ceiling through env. Bumping only the machine memory still leaves Node capped low, so the build dies at the same spot. Both have to move together for the fix to take. Note that large may fall outside the free tier, so check your billing plan first.

Fix 3: Reduce what goes into the bundle in the first place

Adding memory is treating the symptom. If your app is going to keep growing, structurally reducing the number of modules in the bundle pays off longer. Enabling inline requires in metro.config.js keeps the number of modules loaded at once lower.

// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
 
const config = getDefaultConfig(__dirname);
 
config.transformer.getTransformOptions = async () => ({
  transform: {
    experimentalImportSupport: false,
    inlineRequires: true,
  },
});
 
module.exports = config;

For image assets, keep large PNGs out of the JS bundle by swapping any require-referenced images for optimized versions. When I moved my wallpaper apps' high-resolution images to remote delivery, the memory the bundler consumed dropped visibly. Not hoarding assets locally is, in my experience, the single most effective long-term prevention.

If it dies in Android's Gradle step, suspect a different ceiling

Here's a confusing one: an Android build can throw a similar out-of-memory error that is actually Gradle (the JVM) running out of heap, not Node.js. If the log says Java heap space or GC overhead limit exceeded rather than JavaScript heap, you're raising the wrong ceiling. In that case, adjust the JVM arguments in android/gradle.properties.

# android/gradle.properties
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m

No amount of bumping NODE_OPTIONS will touch this. Just remember that one word in the error message — JavaScript versus Java — tells you where to fix it, and you'll avoid a lot of wasted trial and error. Early on I confused the two and burned time poking at the Node side. Once I trained myself to read the subject of the log line first, recovery got much faster.

Habits that keep it from coming back

This error tends to show up unannounced precisely when your app is doing well. I've developed apps solo since 2014, and on the way to a cumulative 50 million downloads I hit this same wall every time features and assets piled up. That's why I now put NODE_OPTIONS into the CI build profile from day one, and make a habit of checking the change in bundle size whenever I add assets.

As your next step, add NODE_OPTIONS=--max-old-space-size=8192 locally and see whether the build gets through. If it does, all that's left is folding it into the permanent settings above, and you'll stay clear of this error for a good while. I hope this helps if you've been stuck watching it fail at the same spot.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-05-03
5 Things to Check First When Rork Shows 'Unable to Resolve Module'
Walk through the five most common causes of the 'Unable to resolve module' error in Rork, React Native, and Expo projects, with the exact commands and the order in which to check them.
Dev Tools2026-04-25
Why Your Rork App Icon Won't Update — Cache Fixes for iOS and Android
Replaced your Rork app icon but still seeing the old one? Walk through the layered causes — iOS SpringBoard cache, EAS Build cache, missing Android adaptive icons — and the exact fixes that get the new icon to stick.
Dev Tools2026-04-24
Diagnosing Metro Bundler Freezes and Broken Fast Refresh in Rork Apps
When your Rork-generated Expo app stops picking up code changes or Metro freezes mid-bundle, here is the diagnostic order and the safe reset steps that actually work.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →