flutter vs react-native: who owns the pixels, and who borrows the platform's
Flutter ships its own rendering engine and paints every pixel through Skia and Impeller; React Native maps React components onto the native widgets each platform already provides. That one split decides your upgrade path, your binary size and the kind of team that will be productive on day one.
At a glance
| Project | flutter/flutter | react/react-native |
|---|---|---|
| Licence | BSD-3-ClausePermissive: commercial use allowed | MITPermissive: commercial use allowed |
| Maintenance | Commits in the last six monthsLast push November 7, 2026 | Commits in the last six monthsLast push November 7, 2026 |
| Language | Dart | C++ |
| GitHub stars | 181,086 | 126,871 |
| Read more | Our analysisGitHub | Our analysisGitHub |
Star history
- flutter/flutter181,086 ★ · +3,216
- react/react-native126,871 ★ · +626
| Repository | 2026-07-21 | 2026-11-07 |
|---|---|---|
| flutter/flutter | 177.9k | 181.1k |
| react/react-native | 126.2k | 126.9k |
Which one to choose
Choose flutter if you need identical rendering on every platform, want one Dart codebase for mobile, web and desktop, and can absorb a fast release cadence with a documented breaking-changes page. It is also the better fit when you expect to write custom drawing, animation or a heavily branded UI that must not drift between iOS and Android.
Choose react-native if your team already writes React, you want the platform's own widgets, gestures and accessibility behaviour, and you are willing to start through Expo and manage native dependencies. It is the wrong choice if you need a single binary for desktop and web only, or if version bumps you cannot schedule are a real risk.
Two rendering models, two kinds of bug
Flutter's README describes a layered architecture that gives you control over every pixel, with compositing that overlays graphics, video, text and controls, and a widget set covering Material and Cupertino. The engine underneath is Skia and Impeller, hardware-accelerated 2D libraries, and Dart compiles to ARM machine code for iOS and Android, JavaScript and WebAssembly for web, and x64 and ARM for desktop. The practical consequence is that your app draws itself. A font, a shadow or a scroll physics curve looks the same on both mobile platforms because the same engine produced it. The cost is that the app carries that engine, and that platform conventions have to be reimplemented rather than inherited.
React Native's README states the opposite premise: primitives render to native platform UI, so the app uses the same native platform APIs other apps do, and gestures, text scaling and accessibility behave the way users expect on each OS. Components, hooks and Suspense are reused across Android, iOS and out-of-tree platforms. You are not shipping a renderer; you are shipping JavaScript and a bridge to widgets the OS already has. That means an unfamiliar control or a new accessibility feature often arrives with the platform, but it also means your UI can look slightly different on each OS, and a bug can live in the native layer rather than in your code.
Neither model is strictly better. Flutter gives you determinism and pixel control. React Native gives you platform fidelity and a smaller conceptual surface. Pick according to which class of bug you would rather debug.
Getting a first build running
Flutter's install path is the SDK itself. The README points at the install page and names editor plug-ins for Visual Studio Code and IntelliJ or Android Studio. One constraint is explicit and easy to miss: the Flutter tool may download resources from Google servers, and when installed from GitHub rather than a prepackaged archive it downloads the Dart SDK from Google servers on first run, and again on upgrade. If your build environment blocks outbound access to Google, that is a blocker before any code is written. Flutter also states that it works with any development tool, or none, and that native code is reachable through FFI on Android, iOS, macOS and Windows as well as platform channels.
React Native's README recommends a Framework and names Expo as a production-grade one, with file-based routing and a standard library of native modules. The command it gives is npx create-expo-app@latest, followed by Expo's getting started guide. The same README says most developers benefit from a framework because navigation, native dependencies and platform tooling are problems the ecosystem has already solved, and it keeps a without-a-framework path for apps that do not fit. Our analysis of react-native says to run npx create-expo-app@latest on a clean machine and confirm the toolchain resolves before committing.
So the first hour differs. Flutter asks you to install a toolchain that talks to Google. React Native asks you to accept an opinionated framework, or to assemble the pieces yourself.
Upgrades, releases and the cost of staying current
Both projects move quickly, and both tell you so. Flutter's README links a breaking-changes page that tracks changes across releases, and our analysis of flutter says to read that page before committing and to avoid the project if you need a slow-moving dependency. The release list shows prerelease builds at a steady clip. Flutter's upgrade path is one tool: the flutter upgrade command, which also triggers the Dart SDK download. That is convenient, but it means an upgrade can change both your framework and your language toolchain at once.
React Native's cadence is visible in its releases: v0.87.0 on 2026-08-11 and v0.87.1 on 2026-08-26. Our analysis of react-native says not to adopt it if you cannot absorb that cadence, and to read the Upgrading page together with the react-native-releases discussions to see what a version bump will demand from your native dependencies. That last point is the real difference. A React Native upgrade can require changes in native modules you do not own, and the project routes release discussion through a working group rather than a single changelog. Flutter's upgrade risk concentrates in the framework and Dart; React Native's concentrates at the boundary between JavaScript and native code.
If you have a native-heavy dependency set, budget upgrade work as a recurring cost, not a one-off.
Operations, binaries and scaling the build
Flutter compiles ahead of time to ARM machine code for mobile, which our analysis of flutter frames as a trade: strong for pixel control, poor for anyone expecting a small dependency tree or a thin binary. The engine travels with the app. In exchange, runtime behaviour is predictable, hot reload keeps state while you edit, and the same Dart code targets mobile, web and desktop. For a team that owns its rendering, that is a good trade. For a team shipping a small utility where install size is the product, it is not.
React Native runs JavaScript against native widgets, with Fast Refresh applying JavaScript changes without rebuilding the native app. That shortens the inner loop, but production still needs native build tooling, signing and store pipelines for each platform, and the framework decision affects how much of that you manage. Expo handles a large part of it; going without a framework means owning it. Our analysis of react-native says to start through Expo unless you have a concrete reason to manage native projects yourself.
Scaling also differs in where expertise sits. Flutter needs Dart plus, for deep integration, FFI or platform channels. React Native needs React plus enough native knowledge to read and patch the modules you depend on. Neither is cheap; they are cheap in different places.
Where each one is the wrong tool
Flutter is a poor fit when the binary must stay thin, when the dependency tree must stay small, or when your organisation cannot schedule framework upgrades against a documented breaking-changes list. It is also a poor fit if your build environment cannot reach Google servers on first run or on upgrade, because the tool downloads the Dart SDK itself. And if your product is a thin layer over platform-specific features that change with each OS release, reimplementing them in Dart is work you would rather not own.
React Native is a poor fit when you need one binary for desktop and web only; our analysis of react-native says exactly that. It is also a poor fit if you cannot absorb a release cadence that shipped 0.87.0 on 2026-08-11 and 0.87.1 on 2026-08-26, or if your native dependencies are numerous and unmaintained, since upgrades land at that boundary. Teams without React experience should not assume the framework choice removes the learning curve; the README's promise is learn once, write anywhere, and the learning is React.
Both are general-purpose and neither is a compromise pick. The failure mode is choosing on popularity rather than on which rendering model your product and team can sustain.
Licence and maintenance: what the table tells you
Flutter is BSD-3-Clause and React Native is MIT. Both are permissive, both allow commercial use and modification, and neither imposes a copyleft obligation on your application code. The difference that matters in practice is not the licence text but the governance behind it. Flutter is Google's SDK, per its README, and the tool's first-run download from Google servers is a dependency on Google infrastructure. React Native's README says it is developed and supported by many companies and individual core contributors, with a React Foundation website, and release discussion happens in a community working group. If your procurement process cares about single-vendor risk, that is a real distinction; if it only cares about the licence, the two are close enough that the licence should not decide.
On maintenance, both repositories show a last push of 2026-09-25 and neither is archived, so both are being worked on. That is the whole of what the maintenance facts support. It does not tell you whether your specific native dependency is maintained, which is where React Native projects actually break, nor whether a Flutter plugin you rely on has kept pace with the framework. Check those dependencies yourself rather than reading the top-level repository activity.
Choosing for a concrete project
A design-led consumer app with a custom visual language, animation and a requirement that iOS and Android match exactly: Flutter, because the engine and widget set are built for that, and the breaking-changes page is the price. A team already fluent in React that needs genuine native widgets, platform accessibility and a fast JavaScript inner loop: React Native through Expo, with the upgrade path treated as scheduled work. A product that must also ship a desktop build from the same code: Flutter's platform set covers mobile, web and desktop, while React Native's out-of-tree platforms exist but the README's own framing is Android, iOS and more. A product that is web and desktop only: neither is the natural pick, and our analysis of react-native says so directly.
An app that embeds into an existing native shell: React Native's integration-with-existing-apps guide is the documented path, and Flutter's platform channels and FFI serve the same purpose from the other direction. A team with no mobile experience and a short deadline: React Native plus Expo removes the most decisions, but only if React is already familiar; otherwise the learning curve is React, not the framework.
Write down which of these you are before reading either README, because both projects are competent and the deciding factor is your constraint, not their quality.
Bottom line
Pick Flutter when you need one rendering model across mobile, web and desktop and can plan around a documented breaking-changes list and a first-run download from Google servers. Pick React Native when your team writes React, you want the platform's own widgets, and you will start through Expo and treat version bumps as recurring work. Before committing to either, verify the two things that decide real projects: run npx create-expo-app@latest on a clean machine if you are leaning React Native, and for Flutter confirm your target platforms and that your build environment can reach Google servers. Then check the maintenance of the specific plugins and native modules you will depend on, since that, not the top-level repository, is where these projects fail in production.
Sources
Was this useful?