· 8 min read
React Native or native: where cross-platform breaks
React Native is our default, but four categories of work send us to native development — and we say so before the contract, not during the build.
In five years we have shipped 9 apps: 11 on React Native, 3 native. Here is how we make that call, because it is usually made on cost, and cost is the wrong criterion.
Why React Native by default
One codebase instead of two. On a typical project — authentication, lists, forms, maps, push notifications — that saves around 40 % against two native teams. Both platforms also stay in step, so you never end up with Android two releases behind.
For eight projects out of ten that is sufficient, and users cannot tell the result from a native app.
Four cases where we say no
1. Background location
Courier or taxi tracking that has to keep running with the app backgrounded and the screen off. iOS and Android aggressively kill background processes, and working around that requires platform-level code. In React Native you do it through native modules — so you write native code anyway, but behind an extra layer. Writing it natively from the start is simpler.
2. Bluetooth and hardware
Apps that talk to a medical device, a lock, a till or a sensor. React Native libraries exist, but on any non-standard firmware you start hitting behavioural differences between iOS and Android, and debugging consumes the savings.
3. Video processing and camera beyond taking photos
Real-time document recognition, filters, augmented reality. These need direct access to camera frames, and passing them across the React Native bridge introduces visible latency.
4. Animation as the product
Not "the card fades in nicely" but products where animation is the point: editors, games, interactive learning tools. Reanimated covers a lot, but if every element animates and it must hold 120 fps, native gives you headroom.
What is not on that list
There is no entry for "long lists", "lots of data" or "complex business logic". Those are the most common client concerns and they are not well founded. A 50,000-item list scrolls fine in React Native, if it is written properly.
The problem is almost never React Native. It is a developer rendering the whole list instead of virtualising it. That is fixed with code, not by changing platform.
How we check before signing
When the description leaves doubt, we build a technical prototype at our own cost: three to five days, one risky feature, tested on real hardware. That is cheaper than discovering four months in that the architecture does not fit.
We did exactly that on the courier app. The main risk was offline synchronisation: the app had to write without a connection and merge correctly afterwards. The prototype took four days and showed React Native would cope. We built it in Flutter for a different reason — the client had an in-house Dart developer who would inherit it.
In short
- Cross-platform is a sound default, not a compromise
- The decision follows the type of work, not the budget
- Four red flags: background location, Bluetooth, camera frame processing, animation as the product
- When in doubt, a week-long prototype beats a four-month mistake
