"Should we build it native or cross-platform" is the first technical question that lands on a founder's desk, and the answer you usually get is a religion lesson rather than a decision aid. The honest version is narrower: both major cross-platform frameworks are legitimate production tools, the differences that matter are specific and documentable, and the choice is mostly about your team and your feature list, not about quality in the abstract.
What each option actually is
Flutter is Google's framework, described in its own FAQ as building "natively compiled applications" for mobile, web, desktop, and embedded devices from a single codebase. On mobile and desktop the Dart code compiles ahead-of-time to native machine code (ARM or x64), and to JavaScript or WebAssembly on the web; Flutter draws every pixel itself through its own rendering engine rather than borrowing the platform's widgets. Google's documented performance target is 60 fps, or 120 on the hardware that supports it.
React Native takes the opposite approach to the same goal: your JavaScript drives the platform's real UI components. Meta's own line is that the primitives "map directly to the platform's native UI building blocks," so the buttons are literally iOS and Android buttons. Meta recommends building new apps on a framework like Expo.
Native means Swift/SwiftUI on iOS and Kotlin/Compose on Android: two codebases, two pipelines, zero indirection.
What actually differs, in documented terms
The performance ceiling is not the axis people think. No official source claims either framework is slow, and both carry flagship-scale apps: Google's own showcase lists NotebookLM and Google Earth on Flutter; "all mobile apps at Shopify are built using React Native." The documented differences are these:
- API lag is real but unquantified. React Native's docs acknowledge "native platform APIs that aren't provided by React Native or an existing library" and give you the escape hatch: write the native module yourself. Flutter offers the same door through platform channels. Neither vendor states a lag window; both just document the workaround exists.
- Binary size is a documented Flutter cost. The engine adds "a small baseline footprint (a few megabytes compressed)," varying by target platform and architecture. React Native publishes no equivalent figure.
- Both stores accept both frameworks. No App Store or Play rule bans them; the only relevant Apple guideline (2.5.2) governs downloaded code, which affects OTA-update tooling, not framework choice.
- Team shape is the hidden variable. One codebase means one team that thinks in one stack. Native means two teams or a rare engineer who holds both.
And the escape hatches are documented, not improvised: when a cross-platform app needs a platform API the framework has not wrapped, both vendors tell you to write the native piece yourself and hand it to the shared layer. The honest read of that is that cross-platform is a floor, not a ceiling; your worst-case cost is a native module inside a shared app, never a rewrite of the app itself.
There is also a question nobody asks out loud: who maintains it. A native iOS app and a native Android app are two roadmaps, two release cycles, two sets of platform deprecations arriving on each vendor's own annual cycle. A cross-platform app is one roadmap, which is most of why small teams choose it and why the cost gap shows up in year two, not month one. The pattern we watch repeat: the second codebase is never double the launch cost, it is double every cost after launch, every fix shipped twice, every OS beta tested twice, every release checklist run in two consoles. That compounding is the number founders should price before they pick, and it is the line most proposals leave off.
Our position
For the apps we build, cash-and-inventory business tools, ordering flows, owner dashboards, cross-platform is the default and Flutter is our pick, because these apps live on forms, lists, and business logic, not on the newest OS surface. The honest triggers for going native: hardware-adjacent features where API lag is the whole product, apps whose primary job is showcasing brand-new OS capabilities, and teams that already have native specialists on staff. If your app is a business tool, you are buying outcomes per dollar, and one codebase buys roughly two platforms for the price of one-point-something.
The takeaway
Ask these before signing anything:
to arm code; react native drives the real os widgets
every shopify mobile app on react native
updates or hand-written native modules; neither
vendor publishes a lag window, so verify per feature
react native publishes no figure
limit is on downloaded code, not how you render
newest apis); cross-platform when the product is
the business logic
This is the same call we made shipping CashTaq in Flutter, and the trade-off conversation we have in week one of every custom software build. If you are weighing native against one codebase for a product you are paying for, send us the feature list.
// sources
// next step
We work this way on client projects too.
Tell us what you are making. We reply with a plan, a timeline, and a price.
