Co-authored with Muhammad Rijalul Kahfi, Dyva Pandhu, Muhammad Widodo, and Johan Sutrisno at Zero One Group. Originally published on Zero One Group Blog.
The mobile development landscape keeps shifting. React Native recently rolled out a new architecture — Fabric, JSI, and TurboModules — promising significantly better runtime performance. Flutter, meanwhile, has long positioned itself on the strength of its ahead-of-time compiled Dart code and single-threaded rendering pipeline.
We wanted to find out: with the new architecture enabled, how does React Native actually stack up against Flutter in practice?
Background
React Native's legacy architecture had a well-known bottleneck: the asynchronous JavaScript bridge. Every JS-to-native call crossed that bridge, adding latency that compounded under load. The new architecture eliminates the bridge entirely — JSI enables synchronous JS-to-native calls, TurboModules enable lazy native module loading, and Fabric brings a new concurrent rendering system.
Flutter never had this problem. Its rendering pipeline runs entirely in Dart, compiled ahead-of-time, with no runtime JS engine involved. The question is whether React Native's architectural improvements are enough to close the gap.
Objective
We set out to compare both frameworks under controlled, real-world-like conditions across three performance dimensions:
- CPU utilization — how hard the processor works during typical app operations
- Memory consumption — how much RAM the app allocates and retains
- Frame rate (FPS) — smoothness of the UI under load
- App startup time and bundle size — cold start performance and binary footprint
All tests ran on both Android and iOS to account for platform-specific optimizations.
Metrics Tracked
We tracked the following for each scenario:
- CPU usage (%)
- Allocated memory (MB)
- Frames per second (FPS)
- Cold start time (ms)
- APK / IPA size (MB)
Implementation Methodology
App Specification
We built equivalent apps in both React Native and Flutter — same UX, same feature complexity, same interaction patterns. This was critical to ensure we were measuring the framework, not implementation differences.
Test Scenarios
Three scenarios were benchmarked:
- App Start — cold start from killed state to first interactive frame
- Resource-intensive Task — heavy computation combined with UI rendering
- Input Responsiveness — rapid user interactions (taps, drags) measured for UI thread responsiveness
Profiling Tools
- Android: Android Profiler (CPU, memory), Perfetto (startup traces)
- iOS: Xcode Instruments (CPU, memory, FPS), MetricKit (startup time)
Test Environment
| Details | |
|---|---|
| Android device | Samsung Galaxy A14 |
| iOS device | iPhone 8 |
| Host machine | MacBook Air M1 2020, 8 GB RAM |
| React Native | New architecture enabled (Fabric + JSI + TurboModules) |
| Build mode | Release (both platforms) |
Manual Testing Approach
Despite wanting full automation, we ran into significant limitations with automated profiling tools in release mode. Detox and integration_test introduce their own performance overhead that skews CPU and memory readings. Maestro doesn't support iOS physical devices in release mode. Appium's automation latency makes frame-rate measurements unreliable.
Automated benchmarking tools often instrument the app in ways that inflate CPU and memory readings. We opted for manual testing with physical devices in release mode to get numbers that reflect actual user-facing performance.
We used physical devices, ran each scenario multiple times, and averaged the results to reduce noise.
Benchmark Results
App Size & Startup Time
On Android, Flutter's APK is significantly smaller than React Native's (19 MB vs 76 MB). Flutter also has a faster cold start on iOS (771.8 ms vs 953.4 ms).
On Android cold start, the picture flips: React Native launches in 593 ms vs Flutter's 1,738 ms — likely due to Flutter's engine initialization overhead. On iOS, React Native's IPA is also slightly smaller (7.3 MB vs 10.5 MB).
| Metric | Flutter | React Native |
|---|---|---|
| APK size (Android) | 19 MB | 76 MB |
| IPA size (iOS) | 10.5 MB | 7.3 MB |
| Cold start — Android | 1,738 ms | 593 ms |
| Cold start — iOS | 771.8 ms | 953.4 ms |
APK size comparison — Flutter vs React Native on Android
IPA size comparison — Flutter vs React Native on iOS
Android cold start time comparison
iOS cold start time comparison
Bundle size differences matter in real-world distribution. A smaller APK means faster downloads, particularly on slower mobile networks — relevant for Southeast Asian markets where a large share of users are on 4G or below.
Scenario 1: Idle / Initial View
Under minimal load (initial render, no active computation), Flutter had lower CPU usage on Android (4–8% vs 15–22% for RN). On iOS the gap was stark — React Native's CPU spiked to 90–222% (multi-core), while Flutter stayed at 21–34%. Memory consumption was higher for React Native on Android; iOS was comparable. FPS results varied by platform, with Android's higher reported rates reflecting the profiler counting all refresh events on a 120 Hz display.
| Metric | Platform | Flutter | React Native |
|---|---|---|---|
| CPU | Android | 4–8% | 15–22% |
| CPU | iOS | 21–34% | 90–222% |
| Memory | Android | 47–152 MB | 170–223 MB |
| Memory | iOS | 49–54 MB | 68–78 MB |
| FPS | Android | 32 | 72–132 |
| FPS | iOS | 56 | 31 |
Scenario 1 — Android CPU utilization
Scenario 1 — Android total memory
Scenario 1 — Android allocated memory
Scenario 1 — iOS CPU utilization
Scenario 1 — iOS total memory
Scenario 1 — iOS FPS
Scenario 2: Resource-Intensive Task
This is where the gap widened. Under sustained heavy computation combined with active UI rendering, Flutter held lower CPU across both platforms. On iOS, React Native's CPU hit 95–300% (multi-core) vs Flutter's 49–54%. Memory was higher in React Native on Android (223–243 MB vs 178 MB); on iOS both were similar. Flutter held a more stable FPS on iOS (54.2 vs 32).
| Metric | Platform | Flutter | React Native |
|---|---|---|---|
| CPU | Android | 7–11% | 17–29% |
| CPU | iOS | 49–54% | 95–300% |
| Memory | Android | 178 MB | 223–243 MB |
| Memory | iOS | 52–53 MB | 52–57 MB |
| FPS | Android | 54 | 105–133 |
| FPS | iOS | 54.2 | 32 |
Scenario 2 — Android CPU utilization
Scenario 2 — Android total memory
Scenario 2 — Android allocated memory
Scenario 2 — iOS CPU utilization
Scenario 2 — iOS total memory
Scenario 2 — iOS FPS
Scenario 3: Input Responsiveness
Under rapid input interaction (continuous taps and drags), React Native's CPU spiked more aggressively — 15–32% on Android and 65–230% on iOS vs Flutter's 8–12% and 24–55% respectively. Flutter's input handling stayed relatively flat, consistent with its single-threaded rendering model that avoids JS-thread contention. FPS was comparable on iOS; Android reported higher values for RN again due to profiler behavior on high-refresh displays.
| Metric | Platform | Flutter | React Native |
|---|---|---|---|
| CPU | Android | 8–12% | 15–32% |
| CPU | iOS | 24–55% | 65–230% |
| Memory | Android | 169–174 MB | 122 MB |
| Memory | iOS | 52–53 MB | 52–61 MB |
| FPS | Android | 52–57 | 111–132 |
| FPS | iOS | 55.5 | 51 |
Scenario 3 — Android CPU utilization
Scenario 3 — Android total memory
Scenario 3 — Android allocated memory
Scenario 3 — iOS CPU utilization
Scenario 3 — iOS total memory
Scenario 3 — iOS FPS
Automation Challenges
It's worth being transparent about the limits of this benchmark:
- Framework overhead: Many testing frameworks introduce their own CPU/memory overhead, making release-mode measurements unreliable
- Timing inconsistencies: Automated inputs (taps, drags) exhibit variable execution timing, which skews latency-sensitive measurements
- Cross-platform parity: Designing identical automation flows for both Flutter and React Native — on both Android and iOS — without introducing framework-specific bias is non-trivial
These constraints reinforced our decision to benchmark manually on physical devices.
Conclusion
Across all three scenarios, Flutter demonstrated more efficient CPU and memory utilization, particularly under resource-intensive workloads. React Native's new architecture is a meaningful improvement over the legacy bridge model, but it still carries the overhead of a JavaScript engine — which shows up under load.
On startup and bundle size, the results split by platform. Flutter wins on Android (smaller APK, faster cold start). React Native has a slight edge on iOS.
If your primary concern is runtime performance — especially for animation-heavy or computation-heavy screens — Flutter's ahead-of-time compiled pipeline gives it a structural advantage that the new RN architecture hasn't fully erased. If iOS cold-start or ecosystem/tooling familiarity matters more, React Native's new architecture is a compelling choice.
Short Analysis
React Native's new architecture (Fabric + JSI + TurboModules) reduces JS-to-native communication overhead substantially. But the JS engine itself remains in the critical path for rendering and logic — and that shows under sustained load.
Flutter's rendering pipeline is structurally different: Dart is compiled AOT, the rendering engine (Impeller/Skia) runs on a dedicated thread, and there's no runtime bridge. This gives Flutter a more predictable performance profile, particularly for frame rates.
These findings are consistent with architectural expectations. They're preliminary — single-device benchmarks on specific scenarios — but they're directionally reliable.
Further Direction
This benchmark is a starting point. For more definitive conclusions, we'd want to:
- Run longer test durations with automated collection to observe performance trends over time
- Test on a wider range of devices — especially low-end hardware where memory and CPU constraints are more pronounced
- Measure background state performance (active vs. background vs. terminated)
- Factor in developer experience: tooling, ecosystem maturity, community support, and hiring pool
One area we deliberately excluded: comparisons with Lynx. While Lynx is sometimes mentioned in cross-platform discussions, it's primarily a document rendering engine — not directly comparable for interactive mobile app development.
Artifacts
The full source code for both the Flutter and React Native benchmark apps is open:
All performance recordings and raw data are available there for reproducibility.
