Hermes vs JSC in React Native: stop arguing, here's when each wins
Hermes has been the default JavaScript engine in React Native since 0.70, and Hermes V1 became the default in 0.84. It compiles JS to bytecode ahead of time; the React Native docs say that for many apps this means faster start-up, less memory, and a smaller app.
JavaScriptCore no longer ships with React Native: since 0.81 it is a separate community package. The reasons people kept it, such as Intl support and debugging tooling, have mostly been addressed in Hermes.
If you're starting a new app, use Hermes. If you're on JSC for legacy reasons, how you switch depends on your React Native version: a build flag before 0.81, removing the community JSC package from 0.81. Test, ship, move on.
The Hermes vs JSC question used to be interesting. In 2026 it mostly isn't. Hermes won. The remaining edge cases are real but narrow.
This post is what each engine actually is, what the benchmarks actually say, and the short list of situations where JSC still makes sense.
What Hermes and JSC actually are
JSC is JavaScriptCore — Apple's JavaScript engine, the one that powers Safari. It's been the React Native default on iOS forever, and on Android it shipped as a port of the same engine. It's a mature, general-purpose engine. It has a JIT compiler. It's optimized for the kind of workloads web browsers see.
Hermes is a different animal. Meta built it specifically for React Native. It doesn't JIT. Instead, it compiles JavaScript to bytecode during the build, ships the bytecode in the app bundle, and runs that bytecode directly at startup. No parse step, no compile step, no warmup.
The architectural difference matters. JSC was designed for "load a page, run JS, throw it away." Hermes was designed for "ship an app, run the same JS on cold start a thousand times, every millisecond counts."
The default has changed
Hermes became the default engine in React Native 0.70 (release post). Hermes V1, a new generation of the engine, became the default on iOS and Android in 0.84 (release post). In 0.81, React Native removed its built-in JavaScriptCore; apps that need JSC use the community package @react-native-community/javascriptcore (release post). Projects created on 0.70 or later use Hermes unless someone turned it off.
Apps that predate those versions and have never been actively migrated are usually still on JSC. The flag was opt-in then; nobody flipped it.
If you're not sure which engine your app uses, check:
- Android:
hermesEnabledinandroid/gradle.properties - iOS:
:hermes_enabled => truein theuse_react_native!block ofios/Podfile - On 0.81 or later, check whether
@react-native-community/javascriptcoreis installed. If it isn't, the app runs Hermes.
What Hermes wins on
Five categories where Hermes is the better choice.
Cold start
This is the headline. Bytecode loads faster than parsing JavaScript. The React Native Hermes docs say that for many apps Hermes improves start-up time, memory use, and app size compared with JavaScriptCore. The size of the gain depends on your app, so measure it.
Measure both platforms separately. The gain on iOS and Android differs from app to app.
Binary size
The React Native docs list smaller app size among Hermes' benefits for many apps. The gain is clearest on Android, where an app using JSC had to bundle its own copy of the engine. On iOS, JavaScriptCore is part of the operating system, so Hermes adds its own runtime to the binary and the net change can go either way.
We don't quote a typical percentage because it depends on your bundle and your dependencies. Compare release builds of your own app.
Memory
Hermes often uses less memory than JSC, particularly during start-up, because precompiled bytecode is memory-mapped from disk instead of being parsed and compiled in RAM.
That matters most on low-memory Android devices, where the OS kills background apps sooner. Profile on the lowest-end devices your users actually have.
Debugging
The React Native debugger and DevTools integration with Hermes is first-class. You get inspector, breakpoints, profiler, and heap snapshots without configuring anything.
JSC debugging in React Native exists but is more fragile. Tooling has consistently improved for Hermes and stagnated for JSC.
It's the supported path
Hermes is the engine React Native bundles and uses by default. JavaScriptCore is now maintained in a separate community package, released separately from React Native, so you depend on that package keeping pace with each React Native release.
What JSC still wins on (and what it doesn't anymore)
The historical reasons people kept JSC:
| Concern | JSC's edge then | Status now |
|---|---|---|
| Intl API | Hermes didn't ship Intl | Hermes implements Intl on Android and iOS using each platform's own facilities, so output can differ slightly between platforms. See the Hermes Intl docs. |
| Long-running JS perf | JIT-compiled JSC outperformed Hermes on tight CPU loops | Can still favor JSC on some CPU-heavy workloads. Measure your own. |
| Library compatibility | A handful of libraries used JSC-only features | Almost all popular libraries now support Hermes. |
| Debugger tooling | Some legacy tooling required JSC | React Native DevTools arrived in 0.76, and the Flipper React Native plugin was removed in 0.74. |
| BigInt, certain regex flags | Hermes lagged on language features | React Native's Babel preset transforms most modern syntax before Hermes runs it, but Hermes doesn't implement everything; with statements and local eval() are excluded, for example. Check the Hermes language features list against what your code uses. |
The one genuine remaining win for JSC: tight, long-running CPU loops in JavaScript. If your app runs a parser, a custom interpreter, a chess engine, a video filter implemented in JS — anything that spends seconds at a time hot in the JS thread — JSC can still be faster. Measure before assuming either way.
Most React Native apps don't have that workload. They have UI code that calls into native and waits. The bottleneck is the native call, not the JS execution. Hermes is fine.
If you think your app might benefit from JSC, measure on your actual workload before switching. The number of teams that have switched back to JSC based on real data is small. The number that switched based on a benchmark someone wrote in 2021 is larger.
How to switch
How you switch depends on your React Native version. The work is testing afterward either way.
React Native 0.80 and earlier (JavaScriptCore built in). Set the engine with a build flag.
Android:
iOS:
Then:
React Native 0.81 and later (JavaScriptCore removed from core). Hermes is the default. To move from JSC to Hermes, remove @react-native-community/javascriptcore and the setup its README added, then rebuild. To stay on JSC, follow that package's installation instructions. From 0.84, the default is Hermes V1.
What to test after:
- Cold start time. Cold-launch the app on a real device, time it. Should be faster on Hermes; if it's slower, something else is going on.
- Any library that does locale-sensitive formatting (Intl). Confirm it still works correctly.
- Any library that uses workers, eval, or dynamic code generation. These are the historical break points.
- Crashlytics or Sentry for the first week. Hermes-specific crashes look different from JSC-specific ones; learn what the new noise floor is.
Measuring before you decide
If your app is large enough that the engine choice might matter, measure rather than argue.
The metrics that matter:
- Time to interactive (TTI). Cold launch to the screen the user can use. Hermes usually wins.
- Peak memory. RAM consumed during heaviest screen. Hermes usually wins.
- Steady-state CPU. Time spent in JS execution during a representative user session. JSC sometimes wins.
- Crash-free sessions. Stability under real load. Should be roughly equivalent; differences are usually library bugs, not engine bugs.
- Binary size. Release APK and IPA size. Hermes usually wins.
Run the test on a representative low-end device. The high-end Pixel and the latest iPhone will hide differences that real users will feel.
Upgrading and unsure about engines?
Engine choice usually rides on a React Native upgrade — the version you target dictates which Hermes features are available, and what your dependencies expect. Run the free scanner against your lockfile to see your React Native version and which installed package versions have published security advisories before you flip the flag.
Frequently Asked Questions
What is Hermes in React Native?
Hermes is a JavaScript engine built by Meta specifically for React Native. It compiles JavaScript to bytecode ahead of time, which means apps don't have to parse and compile JS on every cold start. The React Native docs say that for many apps it improves start-up time, memory use, and app size compared with JavaScriptCore (JSC). It has been the default engine since React Native 0.70, and Hermes V1 has been the default since 0.84.
Is Hermes faster than JSC?
For start-up, usually yes, though the size of the gain varies by app and platform. For steady-state JavaScript execution, the picture is more mixed. JSC has a more mature optimizing compiler and can outperform Hermes on long-running, CPU-heavy JavaScript. But most React Native apps aren't CPU-bound in JS — they're bound by native UI work, network calls, or rendering. The cold-start win matters more in practice than the steady-state gap.
When should I use JSC instead of Hermes?
Rarely. The cases that used to favor JSC — Intl API support, certain regex features, debugging tooling — have largely been addressed in current Hermes versions. The remaining edge cases are apps with a specific library that depends on a JSC-only behavior (rare), or teams that have validated a measurable steady-state performance advantage on their workload. For everyone else, Hermes is the default and should stay the default. On React Native 0.81 and later, JSC also means depending on a separate community package.
Does Hermes support the Intl API?
Yes, with platform differences. Early Hermes releases didn't ship Intl, which broke libraries that used Intl.NumberFormat, Intl.DateTimeFormat, and similar APIs. Hermes now implements Intl on Android and iOS using each platform's own facilities, so results can vary slightly by platform and OS version; the Hermes Intl docs list what is supported. If you saw an Intl-shaped error on an old project, upgrading React Native is usually the fix, not switching to JSC.
How do I switch between Hermes and JSC in React Native?
On React Native 0.80 and earlier: set hermesEnabled=true (or false) in android/gradle.properties, and :hermes_enabled => true (or false) in the use_react_native! block in ios/Podfile, then run pod install. On 0.81 and later, JavaScriptCore is no longer built in: Hermes is the default, and using JSC means installing @react-native-community/javascriptcore per its README. Either way it is a build-time choice, so clear builds, reinstall, and test.
Does the New Architecture require Hermes?
No. The community JavaScriptCore package's setup instructions cover New Architecture apps. Practically, use Hermes: it is the engine React Native bundles and uses by default, while JSC depends on a community package released separately from React Native.