ADR Reference: ADR-MOB-002
Platform selection is the highest-stakes technology choice in mobile engineering. It determines team structure, hiring pool, five-year total cost of ownership, performance ceiling, and the feasibility of certain device API feature categories. This ADR establishes the structured evaluation framework that must be applied at project initiation — replacing informal, preference-driven decisions with weighted criteria and documented rationale.
| Field |
Value |
| ADR Reference |
ADR-MOB-002 |
| Version |
1.0 |
| Date Raised |
May 2025 |
| Review Date |
November 2025 |
| Author |
Solutions Architecture Practice — Ascendion |
| Status |
ACCEPTED |
| Domain |
Mobile Architecture |
| ARB Approval |
Required |
| Stakeholders |
Solutions Architects · CTOs · Mobile Engineering Leads · Client Technology Decision-Makers |
Executive Summary
Decision: A context-driven platform selection framework is adopted. Flutter is the preferred default for new cross-platform mobile applications. Pure Native (separate Kotlin and Swift codebases) is mandated when performance SLA requires frame latency below 16ms, deep device API access is required, or regulatory requirements mandate platform-native attestation. React Native is permitted for teams with existing JavaScript and TypeScript capability. MAUI is permitted only for organisations with an existing .NET mobile codebase. Kotlin Multiplatform is adopted for sharing business logic when platform-native UI is required on both platforms.
Decision Drivers
| Priority |
Quality Attribute |
Weight |
Rationale |
| 1 |
Performance & UX Fidelity |
22% |
Frame rate SLA, startup time, animation smoothness |
| 2 |
Device API Access Depth |
18% |
NFC, custom camera, BLE, SecureEnclave, biometric |
| 3 |
Development Speed |
16% |
Time to first release, parallel development overhead |
| 4 |
Total Cost of Ownership (5yr) |
15% |
Team size, tooling, hiring premium, maintenance |
| 5 |
Team Skills & Ecosystem |
12% |
Existing capability, hiring pool, community size |
| 6 |
Maintainability |
9% |
Framework stability, vendor commitment, tech debt |
| 7 |
Security & Attestation |
5% |
Play Integrity, AppAttest, regulatory compatibility |
| 8 |
Regulatory Compliance |
3% |
Data residency, BSP Circular 982, PDPA |
Considered Options
Option A — Flutter (PREFERRED DEFAULT)
Dart with the Impeller rendering engine. 95% of native performance, 0.58× baseline TCO. The default for new cross-platform apps with standard device APIs. Weighted score: 4.38 / 5.0
Shared domain logic with native UI per platform. 100% performance ceiling (native UI), 0.80× TCO. Adopted for complex shared domain logic with two native UI teams. Weighted score: 4.09 / 5.0
Option C — React Native (New Architecture)
JSI + Fabric. 85–90% of native performance, 0.65× TCO. Permitted for teams with existing JS/TS mobile capability and Expo workflow investment. Weighted score: 3.52 / 5.0
Option D — MAUI (.NET) (RESTRICTED)
C# / .NET 8. 88% of native performance, 0.70× TCO. Permitted only for organisations with an existing .NET mobile codebase. Not for greenfield projects. Weighted score: 3.42 / 5.0
Option E — Pure Native (Kotlin + Swift)
Separate Kotlin/Jetpack Compose and Swift/SwiftUI codebases. 100% performance ceiling, 1.0× baseline TCO. Mandated when frame rate SLA < 16ms, deep device API access, or regulatory attestation is required. Score is context-dependent — selected on hard requirements, not weighted average.
Decision
Platform is selected by applying the decision rules below. Flutter is the default; any deviation requires documented rationale and ARB review.
| Condition |
Platform Decision |
| Frame rate SLA < 16ms OR deep native API (NFC, custom camera, BLE) |
Pure Native |
| New cross-platform app, standard device APIs |
Flutter (DEFAULT) |
| Existing JS/TS mobile team, React ecosystem investment |
React Native New Architecture |
| Existing .NET codebase, C# team |
MAUI (restricted) |
| Complex shared domain logic, two native UI teams |
Kotlin Multiplatform + Native UI |
| Platform |
Weighted Score |
Performance Ceiling |
TCO Multiplier |
Recommended When |
| Pure Native (Kotlin + Swift) |
Context-dependent |
100% |
1.0× baseline |
Frame rate < 16ms SLA, deep device API, regulatory attestation |
| Flutter (Dart, Impeller) |
4.38 / 5.0 |
95% of native |
0.58× |
Default for new cross-platform apps |
| React Native (New Architecture) |
3.52 / 5.0 |
85-90% of native |
0.65× |
Existing JS/TS mobile team, Expo workflow |
| MAUI (.NET) |
3.42 / 5.0 |
88% of native |
0.70× |
Existing .NET mobile codebase only |
| Kotlin Multiplatform |
4.09 / 5.0 |
100% (native UI) |
0.80× |
Complex shared domain logic, two native UI teams |
Trade-off Analysis
| Trade-off Accepted |
Consequence |
Mitigation |
| Flutter uses own rendering engine |
Platform-native feel requires deliberate implementation |
Flutter Material 3 and Cupertino libraries approximate native behaviour |
| Flutter deep native API access requires platform channels |
NFC, custom camera need native Kotlin/Swift modules |
Assess device API requirements in discovery. If > 3 complex channels, evaluate native. |
| React Native New Architecture migration in progress |
Not all libraries migrated from Bridge |
Audit all dependencies for New Architecture compatibility before project start |
Implementation Guidance
- Apply the eight weighted criteria at project initiation — document the score for each candidate platform
- Run a two-day technical spike on the highest-risk screen before committing to any platform
- Default to Flutter unless a decision rule mandates otherwise — record the rule that applies
- For Flutter, audit device API requirements; if more than 3 complex platform channels are needed, re-evaluate Pure Native
- For React Native, confirm and document a New Architecture (JSI + Fabric) adoption plan before sprint 1
- For any non-Flutter cross-platform selection, raise an ARB review with documented rationale
- Configure the CI/CD pipeline (ADR-MOB-003) for the selected platform once chosen
Compliance Checkpoints
| Checkpoint |
Trigger |
Owner |
SLA |
| Platform Selection Review |
Any platform other than Flutter for a new cross-platform engagement |
ARB |
Before sprint 1 |
| React Native New Architecture Plan |
Any React Native selection |
Solutions Architect |
Before sprint 1 |
| Native Cost Justification |
Pure Native costing > 40% above Flutter equivalent |
ARB |
Before commitment |
| Mid-Project Platform Switch |
Any platform change after development start |
ARB (emergency) + Client CTO |
Sign-off before switch |
| Reference |
Title |
Relationship |
| ADR-MOB-001 |
Mobile Architecture Pattern |
Architecture pattern applied once platform is chosen |
| ADR-MOB-003 |
Mobile CI/CD Pipeline |
CI/CD pipeline configured per platform selected here |
| ADR-SEC-011 |
Mobile Security Controls |
Attestation capabilities depend on this platform decision |
Flowchart
%%{init:{'theme':'base','themeVariables':{'fontSize':'14px','fontFamily':'IBM Plex Sans, system-ui, sans-serif','primaryColor':'#DBEAFE','primaryTextColor':'#1e3a5f','primaryBorderColor':'#2563EB','lineColor':'#374151','clusterBkg':'#F9FAFB','clusterBorder':'#D1D5DB','edgeLabelBackground':'#FFFFFF'},'flowchart':{'curve':'orthogonal','padding':30,'nodeSpacing':65,'rankSpacing':75,'useMaxWidth':true}}}%%
flowchart TD
START(["<b>New Mobile Project</b><br/>Platform Decision Required"])
Q1{"<b>Frame rate SLA < 16ms?</b><br/>OR deep device API needed?<br/>NFC · Custom Camera · BLE<br/>SecureEnclave Crypto"}
Q2{"<b>Existing JS/TS</b><br/>mobile team?"}
Q3{"<b>Existing .NET</b><br/>mobile codebase?"}
Q4{"<b>Complex shared</b><br/>domain logic?<br/>Two native UI teams?"}
NATIVE["<b>Pure Native</b><br/>Kotlin + Jetpack Compose<br/>Swift + SwiftUI<br/>Performance: 100%<br/>TCO: 1.0× baseline"]
FLUTTER["<b>Flutter — DEFAULT</b><br/>Dart · Impeller Renderer<br/>Performance: 95% native<br/>TCO: 0.58× baseline<br/>Weighted score: 4.38/5.0"]
RN["<b>React Native</b><br/>New Architecture · JSI + Fabric<br/>Performance: 85–90%<br/>TCO: 0.65× baseline"]
MAUI["<b>MAUI — RESTRICTED</b><br/>C# · .NET 8<br/>Existing .NET only<br/>Not for greenfield projects"]
KMP["<b>Kotlin Multiplatform</b><br/>Shared domain logic<br/>Native UI per platform<br/>Performance: 100%"]
subgraph ARB["⚠ ARB Review Required"]
direction LR
A1["Non-Flutter cross-platform"]
A2["RN without New Arch plan"]
A3["Native >40% above Flutter cost"]
A4["Mid-project platform switch"]
end
START --> Q1
Q1 -->|"YES"| NATIVE
Q1 -->|"NO"| Q2
Q2 -->|"YES"| RN
Q2 -->|"NO"| Q3
Q3 -->|"YES"| MAUI
Q3 -->|"NO"| Q4
Q4 -->|"YES"| KMP
Q4 -->|"NO"| FLUTTER
NATIVE & RN & MAUI & KMP -.->|"Document rationale"| ARB
style START fill:#1D4ED8,stroke:#1e3a5f,color:#ffffff
style Q1 fill:#FEF9C3,stroke:#CA8A04,color:#713f12
style Q2 fill:#FEF9C3,stroke:#CA8A04,color:#713f12
style Q3 fill:#FEF9C3,stroke:#CA8A04,color:#713f12
style Q4 fill:#FEF9C3,stroke:#CA8A04,color:#713f12
style NATIVE fill:#DCFCE7,stroke:#16A34A,stroke-width:2px,color:#14532D
style FLUTTER fill:#1D4ED8,stroke:#1e3a5f,stroke-width:3px,color:#ffffff
style RN fill:#EDE9FE,stroke:#7C3AED,stroke-width:2px,color:#4C1D95
style MAUI fill:#E5E7EB,stroke:#4B5563,stroke-width:2px,color:#374151
style KMP fill:#DBEAFE,stroke:#2563EB,stroke-width:2px,color:#1e3a5f
style ARB fill:#FEE2E2,stroke:#DC2626,stroke-width:2px
style A1 fill:#FCA5A5,stroke:#DC2626,color:#7f1d1d
style A2 fill:#FCA5A5,stroke:#DC2626,color:#7f1d1d
style A3 fill:#FCA5A5,stroke:#DC2626,color:#7f1d1d
style A4 fill:#FCA5A5,stroke:#DC2626,color:#7f1d1d
References
- Flutter — Architecture Overview. docs.flutter.dev/app-architecture
- JetBrains — Kotlin Multiplatform. kotlinlang.org/docs/multiplatform.html
- Meta — React Native New Architecture. reactnative.dev/docs/new-architecture-intro
- Airbnb Engineering — Sunsetting React Native. medium.com/airbnb-engineering, 2018.
- Nubank Engineering — Flutter at Scale. building.nubank.com.br
⚠ Platform Choice by Team Familiarity Only — Selecting React Native because the team knows JavaScript without evaluating performance requirements or device API needs.
CORRECT: Team familiarity scores 12% weight — not the sole criterion. A team learns Dart in 3–6 weeks. Recovering from a wrong platform choice costs months.
⚠ Cross-Platform Start, Native Rewrite Mid-Project — Airbnb 2018: committed to React Native for two years, discovered brownfield integration and debugging limitations, rewrote in native. Switch cost exceeded choosing native initially.
CORRECT: Two-day technical spike on the highest-risk screen before platform commitment.
End of Document
Maintained by
Architecture Council
Review Cadence
Annually or upon any
Tier 2 architectural change
Change Requests
Submitted as RFC to the
Architecture Council for review
Version History
Maintained in version
control alongside this document