Unpacking the birth of Hermes at Meta: the slow startup and memory-hungry problems on low-end mobile devices that forced the creation of a dedicated engine. Comparing Hermes with V8, JavaScriptCore, and SpiderMonkey, plus its three main advantages: startup time, memory footprint, and bytecode precompilation.

In episode 0 we set up our environment — Node.js, React Native, and the Hermes repo. Now it's time to answer the most fundamental question: why does Hermes exist?
Episode 1 covers the background behind Hermes' birth at Meta, compares it with other engines, and dissects its main advantages. By the end of this episode, you'll know when Hermes is the right choice — and when you should avoid it.
Before Hermes, React Native on Android used JavaScriptCore as its engine. This initially made sense: one engine for both iOS and Android. But as React Native began to be used for large-scale apps on cheap devices, Meta discovered real problems:
JIT is indeed fast once functions are warmed up, but that warming-up process is exactly the problem. On mobile devices with 1-2 GB of RAM, the cost of parsing, compiling, and JIT warmup during cold start is very expensive.
Hermes was developed internally by the React Native team at Meta starting in 2016, with a single philosophy: an engine optimized for mobile-first JavaScript, not a port from desktop. The team prioritized two things above all else: short startup time and a small memory footprint.
Hermes was announced publicly at React Native EU in July 2019 and immediately open-sourced. Adoption moved fast:
The big design decision in Hermes was removing the JIT at runtime. All compilation happens before the app runs. The result? The engine stays a pure interpreter on device — fast to start, RAM-efficient, and predictable.
To understand Hermes' position, compare it with the three major engines:
engine: V8
pembuat: Google
strategi: JIT penuh (TurboFan, Maglev)
fokus: Desktop, server, Chrome
pakai_di: Node.js, Chrome, edge
engine: JavaScriptCore
pembuat: Apple
strategi: Interpreter + JIT (FTL, B3)
fokus: Mobile, browser
pakai_di: Safari, WebKit
engine: SpiderMonkey
pembuat: Mozilla
strategi: Interpreter + JIT (Ion, Warp)
fokus: Browser, Firefox
pakai_di: Firefox, embedded
engine: Hermes
pembuat: Meta
strategi: AOT bytecode + interpreter murni
fokus: Mobile, embedded, edge
pakai_di: React Native, edge runtimesThe most striking difference is in strategy. V8 chases peak throughput with sophisticated JIT; Hermes rejects JIT and chases deterministic startup. For mobile apps that only live a few minutes, peak throughput matters less than the first 300 ms that the user actually feels.
// In Hermes, this function runs immediately once the bytecode is loaded.
// There is no "JIT warmup" phase like in V8.
function renderHome() {
const items = fetchInitialFeed();
return items.map((item) => <FeedItem data={item} />);
}On V8, the first call to renderHome is still interpreted before being JIT-compiled. In Hermes, all of this is already compiled bytecode from the start — deterministic and fast.
Hermes' first advantage is predictable startup time. Because the source is already compiled to bytecode at build time, the runtime doesn't need to parse and compile JavaScript when the app launches. Meta's internal measurements recorded a significant drop in React Native app startup time on low-end Android devices. In episode 5, we'll optimize this startup even further with bytecode prepackaging.
The second advantage is a small memory footprint. Without JIT, no memory is allocated for compiled machine code at runtime. Hermes also uses string compression techniques and a lightweight object model. Property hashes are computed once at compile time, so the object layout stays compact. On devices with limited RAM, this difference can determine whether an app stays alive or gets killed by the operating system.
The third advantage is bytecode precompilation. JavaScript source is converted into a Hermes bytecode file (HBC format) during the build process, and this file ships with the app. The benefits are twofold:
Try compiling right away with the compiler you cloned in episode 0:
cd hermes
echo "print('hello hermes');" > hello.js
build/bin/hermesc -emit-binary hello.js -out hello.hbc
build/bin/hermes hello.hbcThe command build/bin/hermesc -emit-binary turns the source into bytecode, then build/bin/hermes hello.hbc runs it. We'll cover the full instructions for building the hermesc binary in episode 3.
To be honest: Hermes doesn't excel in every scenario. Avoid Hermes when:
For the majority of React Native apps, this trade-off is very favorable. For typical server workloads, V8 remains the champion.
Now you know where Hermes comes from and its competitive advantages. Here's what you must take away:
Next, in episode 2 we dissect Hermes' internal architecture: the parser, bytecode compiler, garbage collector, and interpreter — how the four work together to execute JavaScript. See you there!