How to Optimize Your Android App Startup Time with Hermes

Mike Grabowski

blog content

Need help with React Native?
hire us
Our React Native EU Conference is back
register nowlearn more


The following article is a part of The Ultimate Guide to React Native Optimization and describes how to optimize your Android application startup time with Hermes.

Why is it important?

As you know, well-optimized performance and running at maximum possible speed are some of the most important factors of successful mobile apps. They have a huge influence on how your app is perceived by users and may significantly impact its' ROI. What's more, well-performing apps achieve higher metrics in Google Play Store, which raises the ranking in in-store searches. In this article, we will show you how to achieve it with the help of Hermes.

In the previous parts of our guide, we have discussed:

Be sure to check them out. Now let's jump into the main topic.

Optimizing an Android app startup time

Issue: loading too many packages during the startup time

You’re loading a lot of Android packages during the startup time which is unnecessary. Also, you’re using an engine that is not optimized for Android.

Users expect applications to be responsive and to load fast. The one that fails to meet these requirements can end up receiving bad ratings in the App Store or Play Store. In the most extreme situations, it can even get abandoned in favor of its competition.

user waiting for the app to load

It is not easy to describe the startup time with a single metric. It’s because there are many different stages of the loading phase that can affect how “fast” or “slow” the app feels. For example, in the Lighthouse report, there are six performance metrics used to profile your web application. One of them is Time to Interactive (TTI in short), which measures the time until the application is ready for the first interaction.

There are quite a few things that happen from the moment you press the application icon from the drawer for the first time.

the process of starting an app

The loading process starts with a native initialization (1), which loads the JavaScript VM and initializes all the native modules. It then continues to read the JavaScript from the disk (2), loads it into the memory, parses and starts executing. The details of this operation were discussed earlier in the section about choosing the right libraries for your application.

In the next step (3), React Native starts loading React components and sends the final set of instructions to the UIManager. Finally, the UIManager processes the information received from the JavaScript and starts executing native instructions (4) that will result in the final native interface.

As you can see on the diagram above, there are two groups of operations that influence the overall startup time of your application.

what influences the startup time of an app

The first one involves operations 1 and 2 from the diagram and describes the time needed for React Native to bootstrap (to spin up the VM and for the VM to execute the JavaScript code). The other one includes the remaining operations 3 and 4 and is associated with the business logic that you have created for your application. The length of this group is highly dependent on the number of components and the overall complexity of your application.

This section focuses on the first group  –  the improvements related to your configuration and not the business logic itself.

If you have not measured the overall startup time of your application or have not played around with things such as Hermes yet - keep on reading.

Long startup times and slow UX on Android can be one of the reasons your app gets bad rating and ends up being abandoned.

Creating applications that are fun to play with is extremely important, especially considering how saturated the mobile market already is. Now, all mobile apps have to be not only easy to understand and intuitive. They also should be pleasant to interact with.

There is a common misconception that React Native applications come with a performance trade-off compared to their native counterparts. The truth is that with enough attention and configuration tweaks, they can load just as fast and without any considerable difference.

Solution: turn on Hermes to benefit from a better performance

While React Native application takes care of a native interface, it still requires JavaScript logic to be running at a runtime. To do so, it spins off its own JavaScript virtual machine. By default, it uses JavaScriptCore. This engine is a part of WebKit and by default is only available on iOS. Now it’s also a preferred choice for compatibility purposes on Android. It’s because using the V8 engine (that ships with Chrome) could potentially increase the differences between Android and iOS, and make sharing the code between the platforms way more difficult.

JavaScript engines don’t have an easy life. They constantly ship new heuristics to improve the overall performance, including the time needed to load the code and then to execute it. To do so, they benchmark common JavaScript operations and challenge the CPU and memory needed to complete this process.

Note: The V8 team has recently published a blog post on improving the regular expressions’ performance. Be sure to check it out.

Most of the work of developers handling the JavaScript engines is being tested against major and most popular websites, such as Facebook or Twitter. It is not a surprise that React Native uses JavaScript in a different way. For example, the JavaScript engine made for the web doesn’t have to worry much about the startup time. The browser will be most likely already running at the time of loading a page. Because of that, the engine can shift its attention to the overall CPU and memory consumption, as web applications can perform a lot of complex operations and computations, including 3D graphics.

As you could see in the performance diagram presented in the previous section, a JavaScript virtual machine consumes a big chunk of the app’s total loading time. Unfortunately, there is little you can do about it unless you build your own engine. That’s what the Facebook team ended up doing.

developers using hermes

Meet Hermes - a JavaScript engine made specifically with React Native in mind. It is optimized for mobile and focuses on relatively CPU-insensitive metrics, such as the application’s size or the Time to Interactive. Right now, it is only available on Android, with potential future support for iOS.

Before we go into the details of enabling Hermes in existing React Native applications, let’s take a look at some of its key architectural decisions.

Bytecode precompilation

Typically, the traditional JavaScript VM works by parsing the JavaScript source code during the runtime and then producing the bytecode. As a result, the execution of the code is delayed until the parsing completes. It is not the same with Hermes. To reduce the time needed for the engine to execute the business logic, it generates the bytecode during the build time.

Bytecode precompilation with Hermes

It can spend more time on optimizing the bundle using various techniques to make it smaller and more efficient. For example, the generated bytecode is designed in a way so that it can be mapped in the memory without the eager loading of the entire file. Optimizing that process brings significant TTI improvements as I/O operations on mobile devices tend to increase the overall latency.


The majority of modern browser engines use just-in-time (JIT) compilers. It means that the code is translated and executed line-by-line. However, JIT compiler keeps track of warm code segments (the ones that appear a few times) and hot code segments (the ones that run many times). These frequently occurring code segments are then sent to a compiler that, depending on how many times they appear in the program, compiles them to the machine code and, optionally, performs some optimizations.

Hermes, unlike the other engines, is an AOT(ahead-of-time) engine. It means that the entire bundle is compiled to bytecode ahead of time. As a result, certain optimizations that JIT compilers would perform on hot code segments are not present.

On one hand, it makes the Hermes bundles underperform in benchmarks that are CPU-oriented. However, these benchmarks are not really comparable to a real-life mobile app experience, where TTI and application size takes priority.

On the other hand, JIT engines decrease the TTI as they need time to parse the bundle and execute it in time. They also need time to “warm up”. Namely, they have to run the code a couple of times to detect the common patterns and begin to optimize them.

If you want to start using Hermes, make sure that you are running at least React Native 0.60.4 and turn the following in your <rte-code>android/app/build.gradle<rte-code> :

<rte-code>enableHermes<rte-code> is set to <rte-code>false<rte-code> at the time of writing this content. Be sure to swap it to <rte-code>true<rte-code>.

Benefits: Better startup time leads to better performance. It’s a never-ending story.

Making your application load fast is not an easy task. It’s an ongoing effort and its final result will depend on many factors. You can control some of them by tweaking both your application’s configuration and the tools it uses to compile the source code.

Turning Hermes on is one of the things that you can do today to drastically improve your application’s performance.

Apart from that, you can also look into other significant improvements shipped by the Facebook team. To do so, get familiar with their write-up on React Native performance. It is often a game of tiny and simple improvements that make all the difference when applied at once.

As we have mentioned in the section on running the latest React Native, Hermes is one of those assets that you can leverage as long as you stay up to date with your React Native version.

Doing so will help your application stay on top of the performance game and let it run at maximum speed.


Optimization Adroid app startup time with Hermes may lead to significant improvements both for the technical and business side of your products. I hope that you'll find our tips and solutions useful. If you'd like to read more about the startup time in Android apps, read this article.

Don't forget to read other articles from our guide. In the next one, we will show you how to Optimize your Android application’s size with Gradle settings.


We are the official Facebook partners on React Native. We’ve been working on React Native projects for over 5 years, delivering high-quality solutions for our clients and contributing greatly to the React Native ecosystem. Our Open Source projects help thousands of developers to cope with their challenges and make their work easier every day.

Contact us if you need help with cross-platform or React Native development. We will be happy to provide a free consultation.

Mike Grabowski
Co-founder & CTO of Callstack. Mike is a React Native core contributor and author of many libraries. When he isn't working, he is on a race track.
arrow icon
MORE posts from this author

learn more

More posts from this category

stay tuned

Subscribe to our newsletter

You may unsubscribe from these communications at any time. For details see the Privacy Policy.