Choosing a cross-platform mobile architecture
A practical way to compare native, shared-code, and cross-platform mobile options without framework hype.

Cross-platform mobile architecture decisions are often argued as framework debates. That is the wrong starting point. The better question is what the product needs to share, what must stay native, and where the team can safely carry complexity.
No option is universally best. Native apps, shared business logic, Compose Multiplatform, React Native, Flutter, and web-backed surfaces all trade speed, control, hiring, performance, and platform fit differently.
Start with product surfaces
List the surfaces the app actually needs: onboarding, payments, maps, camera, background work, widgets, push flows, offline sync, account settings, media, wearables, or platform-specific integrations.
The more the product depends on deep platform behavior, the more carefully you should preserve native control. The more it depends on shared workflows and consistent screens, the more shared code can help.
Separate UI sharing from logic sharing
Sharing UI and sharing business logic are different decisions. Some teams benefit from native UI with shared Kotlin or TypeScript domain logic. Others benefit from shared UI because the product needs consistency and the platform-specific surface area is small.
Do not force one answer across the whole app. Hybrid architecture is often more honest: shared models, networking, validation, analytics contracts, and selected screens, with native modules where platform behavior matters.
Count operational complexity
Cross-platform tools can reduce duplicated feature work, but they add their own operational costs. Build tooling, debugging, dependency compatibility, platform release timing, native module maintenance, and hiring profile all matter.
The right architecture is not the one with the smallest code count. It is the one the team can operate reliably through releases.
Protect performance-critical flows
Camera capture, maps, animation-heavy screens, offline sync, and background services deserve specific performance validation. Do not assume a framework will be fine or fail. Prototype the risky flows, measure them, and decide with evidence.
Users do not care which framework is responsible. They care whether the app feels fast, stable, and trustworthy.
Make the decision reversible where possible
Define boundaries so parts of the app can move later. Keep APIs clean, isolate platform adapters, avoid leaking framework types into core domain code, and document the reasons for the choice.
A good mobile architecture is not about winning an argument. It is about giving the product room to ship, learn, and evolve without trapping the team.