Flutter vs. React Native’s New Architecture: Performance Benchmark
A Comprehensive Analysis of Flutter vs. React Native
Choosing between React Native and Flutter can be overwhelming. Both are widely recognized and adopted, with strong use cases and backing from major tech companies (though flutter’s support ecosystem is sometimes questioned — but let’s set that aside).
Typically, factors like community size, tech adoption and programming languages preferences play a pivotal role in making this decision. However, this article aims to set those considerations aside and focus exclusively on performance — a critical aspect that directly impacts user experience and app scalability.
We all know that usually, Flutter outperforms React Native in memory allocation, app size, runtime efficiency largely due to its architecture. But what about React Native’s much-anticipated new architecture? Although it’s now officially released, there appears to be a noticeable gap in up-to-date benchmarks, which prompted me to write this article.
To address this, I conduced a benchmarking analysis of both frameworks. Let’s dive in step by step.
Test overview
To allocate significant device resources and simulate worst-case (bizarre) scenarios, I used three test cases in three different builds
Test cases
- A large list of 1,000 items, where each item is a simple card with an image (details about the images will follow) on the left and a title.
- RN code / Flutter code - A large grid of animated images, reusing the same 1,000 items in two columns. Each images undergoes a cycle of scaling up, rotating 360 degrees while fading out, then to its initial state with animation and repeating infinitely.
- RN code / Flutter code - A large grid with multiple Lottie animations, again using the same 1,000 items in two columns. Each item displays a Lottie animation — selected from a set of 20 isolated animation files, all stored locally within the project.
- RN code / Flutter code
The images
I’m using a set of images in various sizes: 25 local images (stored in the project) — with a combined size of 1 MB — and 25 network images served via a Global CloudFront Distribution.
Also used the Network Link Conditioner to throttle my internet and avoid influencing the results.
Environment
The tests were conducted on simulator devices running on a MacBook M3 Max with 128GB of RAM (possibly overkill since crashes are unlikely, but let's proceed). The Android Emulator used a Pixel 9 Pro XL (API 35), while the iOS simulator ran on an iPhone 15 Pro Max (iOS 18.1).
Except for the FPS tests (performed only on iOS) — these were conducted on a physical iPhone 15 Pro Max (iOS 18.1.1) — since Xcode only allows the use of the Core Animation FPS instrument on physical devices.
Test tools
On iOS, tests were conducted using Instruments (a tool built into Xcode), leveraging the Time Profile to analyze memory allocation, CPU usage and FPS. On Android I used Profiler (tool built into Android Studio)
All the tests were run using Maestro, a mobile UI testing framework (similar to Detox). I chose Maestro to ensure consistency across all tests and avoid influencing the results — for example, by scrolling faster on one device than another. Creating a functional test with Maestro is as simple as this:
appId: com.apprnbenchmark
---
- tapOn: Lottie
- repeat:
times: 6
commands:
- swipe:
duration: 100
start: 50%, 90% # From (50% of width, 90% of height)
end: 50%, 10% # To (50% of width, 10% of height)
Framework and library versions
To be honest, when I first started creating the tests, I was only planning to compare Flutter with React Native (using bare project). However, as I reviewed the React Native documentation, I noticed they strongly recommend starting new projects with Expo.
So, why not include a RN with Expo comparison as well?
- React Native: 0.76.3 (package.json)
- RN Reanimated: 3.16.3
- RN Lottie: 7.1.0 - Expo: 52.0.14 (package.json)
- React Native: 0.76.3
- RN Reanimated: 3.16.3
- RN Lottie: 7.1.0 = - Flutter: 3.24.5 (pubspec.yaml)
- Dart: 3.5.4
- Lottie: 3.1.3 - Maestro: 1.39.2
Benchmark results
I'll split benchmark results into Android and iOS sections, comparing app sizes, resource usage and more. In the end, I'll summarize everything by highlighting the key strengths and weaknesses that worth to be mentioned.
Disclaimer: this article compares the performance of Flutter and RN in their most raw and out-of-the-box configurations, I mean, there's no additional optimizations.
While using third-party libraries like Lottie, Reanimated or default components like FlatList might not reflect fully optimized scenarios, the goal here is to showcase baseline performance for new projects. Maybe a follow-up article may explore these frameworks with applied optimizations for a fairer comparison.
Android
App size
Flutter was able to generate smaller AAB and APK files, outperforming both React Native bare projects and those built with Expo. This was somewhat expected, as Flutter doesn’t require additional libraries like Reanimated, for example
Resources allocation
Again, Flutter outperforms React Native-based projects across all metrics. A fun fact is that Flutter was almost able to maintain the same memory and CPU usage both before the test started and while it was running — at least on Android devices.
It’s worth mentioning that, despite the considerable memory usage on RN projects, I only noticed a slight FPS drop during the Lottie tests on Expo. Aside from that, everything ran smoothly.
Some of the images from the test findings can be seen here.
I also recorded my screen while running two tests, can be watched here.
iOS
App Size
When it comes to App Size, Flutter and RN bare project had the same results here. I used a production .ipa file to generate this chart and was a bit surprised that, on iOS, even with the need to install RN Reanimated, RN still had the same size as Flutter.
Resources allocation
In the first two tests, although RN consumed significantly more resources than Flutter, I didn't notice any frame drops — everything ran smoothly.
Now, when it comes to Lottie animations test case, scrolling became impossible — extremely laggy. I'll talk more about FPS drops later on.
FPS
RN tests started off well with the large list, consistently maintaining 60 FPS with no drops. The Lottie tests also began smoothly, although it was already noticeable that the page was consuming a lot of resources due to the delay in loading. However, a few seconds later, performance deteriorated very fast, struggling to stay above 45 FPS and smooth scrolling became impossible.
Finally, it was time to test the animated images. In this case, FPS remained very stable, consistently holding at 60 with no drops.
In Flutter, FPS drops occurred only once, as highlighted in profile image (right), but they were unnoticeable while scrolling through the app even with a higher GPU usage.
You can check the images from the FPS tests findings here, along with some other screenshots.
Conclusion
So, after all these tests and regardless of programming language preferences, adoption, community support or a bridgeless release, Flutter still comes out as the more performant option compared to RN — with or without Expo.
Flutter stands out for minimal memory and CPU usage, as well as for generating smaller or similarly bundle sizes.
Another downside to RN is the significant effort that developers need to put in optimize performance, just to get close to the level of efficiency that Flutter provides by default. This added complexity can be a dealbreaker for teams looking for a development tool.
In summary, Flutter's consistent efficiency and lower resource consumption make it a strong player, especially for projects where performance is a priority.
Thank you for reading this far! If you'd like to connect with me on LinkedIn, feel free to reach out :)