Choosing Hermes in React Native: Startup Gains, Build Costs, and Compatibility Checks
Hermes compiles JavaScript to bytecode ahead of time, cutting React Native startup and memory. Here is how to enable it, verify it is active, and know when it will break your app.
04 Jul 2026, 21:57 UTC

If your React Native app feels slow to open on mid-range Android phones, the bottleneck is often not your JavaScript logic—it is the engine parsing that logic at launch. React Native ships with JavaScriptCore by default, which interprets and compiles JavaScript while the app is starting. Hermes takes a different approach: it compiles your bundle to bytecode ahead of time, moving that work from the user’s device to your build machine. For many teams, that trade is worth it. For others, it introduces compatibility risks that only surface after release.
What Hermes actually changes
Hermes is a JavaScript engine optimized for React Native. Instead of parsing source text every time the app starts, it executes compact bytecode. The practical effect is twofold: less work on the main thread during startup, and a smaller memory footprint because the engine does not need to hold the same parsing and compilation state that a general-purpose engine like V8 does.
Reported benchmarks suggest startup improvements of up to roughly 30% on mid-range hardware and peak memory reductions of about 20–25% compared with V8. Treat those numbers as directional rather than guaranteed: your actual gain depends on bundle size, device class, and how much native work happens before the JavaScript engine even starts.
Enabling Hermes and proving it is active
Hermes is controlled by build configuration, not a runtime switch. In many React Native versions it is opt-in; in newer templates it may already be the default. Because the flag is easy to miss, an app can silently run JavaScriptCore even when you believe Hermes is enabled.
Android configuration
In android/app/build.gradle, look for the React Native extension block:
project.ext.react = [
enableHermes: true
]
If your project uses a newer React Native version, the setting may live in gradle.properties as hermesEnabled=true. Check both locations.
iOS configuration
For iOS, the equivalent control is typically in the ios/Podfile:
:hermes_enabled => true
Older projects may expose the same choice through an Xcode build setting. After changing the Podfile, run a fresh pod install so the native dependencies rebuild.
Verifying the engine is in use
Configuration alone does not prove Hermes is running. On Android, measure cold startup with the Activity Manager before and after the change:
adb shell am start -W com.example.myapp/.MainActivity
Replace com.example.myapp with your application ID and .MainActivity with your launch activity. Compare the TotalTime or ThisTime values across builds. A meaningful drop suggests the bytecode path is active, though it also confirms that other startup work did not regress.
You can also inspect the build output. Depending on your React Native version, Hermes bytecode artifacts appear under generated build directories—for example, a Hermes directory or .hbc files within the Android build outputs, such as android/app/build/outputs/mapping/release—rather than a plain JavaScript bundle. If you only see the original index.android.bundle in the release assets, the flag likely did not take effect.
The compatibility tax
Hermes is not a free upgrade. It imposes hard platform floors and behavioral differences that can break existing code.
Minimum OS versions
Hermes requires Android API 24+ and iOS 10+. If your app supports older devices, you cannot switch engines without dropping those users or maintaining two build variants.
Dynamic code and polyfills
Because Hermes executes bytecode rather than arbitrary source text, features that rely on runtime compilation are restricted. Libraries that call eval or new Function may fail. Polyfill-heavy code that generates functions on the fly is the most common casualty. Before enabling Hermes, audit your dependency tree for these patterns.
Language feature gaps
Older React Native builds paired with Hermes have lagged behind on some JavaScript proposals. Optional chaining, for example, was unavailable in certain Hermes versions bundled with earlier RN releases. If your codebase uses modern syntax, confirm that your specific Hermes version supports it.
Build time and debugging
Enabling Hermes adds an ahead-of-time compilation step. Expect roughly 5–10 seconds of extra build time on a typical development laptop. Debugging also changes: stack traces in Flipper or Chrome DevTools may show a subset of frames, and some workflows require the Hermes debugger extension to get readable output.
A practical decision framework
Enable Hermes when all of the following are true:
- Your minimum targets are Android API 24+ and iOS 10+.
- Your bundle is large enough that parse time matters on mid-range hardware.
- Your dependencies do not rely on
eval,new Function, or heavy runtime code generation. - You can absorb a small build-time increase and adjust your debugging workflow.
Stay on JavaScriptCore if you support older OS versions, depend on libraries that break under bytecode execution, or cannot verify that dynamic code paths are safe.
How to check the result
After enabling Hermes, do not trust the flag alone. Run the adb shell am start -W command on a physical mid-range device, not only an emulator, and compare cold-start times against your previous JavaScriptCore build. Smoke-test any library that might generate code at runtime. On iOS, use Xcode Instruments to compare memory footprints between the two builds. If startup improves and no library fails, the trade is likely favorable for your app. If dynamic evaluation breaks or the OS floor excludes too many users, revert the build flag and keep JavaScriptCore.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.