Every product leader who has shipped on more than one platform knows the quiet tax. The same login screen, the same checkout, the same settings page — written three times, in three languages, by three teams that never quite agree. iOS in Swift. Android in Kotlin. Web in TypeScript. One feature becomes three engineering budgets, three bug queues, and three release trains that drift apart.
I've watched teams burn their best people keeping three implementations in sync instead of building the next thing. The redundancy isn't a one-time cost. It compounds.
The arithmetic of three surfaces
The mobile market gives you no choice about coverage. Android holds the large majority of global share outside North America; iOS dominates the high-value North American and Japanese segments; and a web fallback is table stakes for desktop and shareable links. StatCounter's figures put Android above 70% of global mobile usage and iOS in the high teens — you cannot serve the market with one. So you staff three stacks.
The cost shows up in three places. First, build cost: the same logic re-implemented three times, with platform-specific bugs each time. Second, maintenance: a defect fixed on iOS still lives on Android and web until someone notices. Third, drift: the three versions quietly diverge in behavior, so your «one product» feels inconsistent to users who switch devices.
Side by side
| Dimension | Native iOS + Android + Web | Universal runtime (one codebase) |
|---|---|---|
| Engineering stacks | Three (Swift, Kotlin, TS) | One |
| Build cost | Feature × 3 | Feature × 1 |
| Bug surface | Triplicated, platform-specific | Single, shared |
| Release cadence | Three trains, drift | One pipeline |
| Reach | Must cover all platforms | Runs across hosts/platforms |
| Team size | Three specialists | One cross-platform team |
A universal runtime changes the unit of work. You write the service once against a runtime that provides identity, payments, and UI components consistently on every host and platform. The native differences — how a button looks on iOS versus Android — are handled by the runtime's platform adapters, not by your re-implementation. The open-catalog model means the same mini-program runs inside many host apps without you porting it per host.
The honest caveat: a runtime is not zero effort. Platform-native capabilities still need mapping, and you trade the freedom of three fully bespoke stacks for the constraint of one runtime's API surface. But the trade turns a structural cost — three copies of everything — into a manageable one. For most teams, that's the difference between shipping and not shipping.
If you're staffing three teams to say the same thing three ways, the question isn't «which cross-platform tool.» It's «why are we paying to say it three times at all.»