| name | mobile-architecture-decisions |
| description | How to write and maintain Architecture Decision Records (ADRs) for mobile teams, and the canonical set of decisions every mobile project must record. Use when starting a project or when an architectural change is being proposed. |
Mobile Architecture Decisions
Instructions
Most mobile architecture debates repeat across projects. Capture decisions in Architecture Decision Records (ADRs) so the agent and future contributors inherit context instead of re-arguing it.
1. ADR Format
Keep ADRs short, markdown, and numbered. One decision per file under docs/adr/.
# ADR-0007: Use Coroutines + Flow for Android Domain Layer
## Status
Accepted 2026-04-19. Supersedes ADR-0003.
## Context
- We had RxJava in the legacy Android app; iOS uses Combine.
- New domain logic is being shared via KMP.
## Decision
Use Kotlin Coroutines and Flow in the shared domain and Android presentation.
Bridge to Swift via KMP suspend interop; do not introduce RxSwift on iOS.
## Consequences
+ One async primitive across Kotlin codebases.
+ Structured concurrency is a first-class feature.
- Swift side needs adapter helpers for Flow collection.
- RxJava usages in legacy modules must be migrated or frozen.
Lifecycle states: Proposed, Accepted, Superseded by ADR-NNNN, Deprecated. Never delete ADRs.
2. Canonical Mobile ADR Set
Every mobile project should have accepted ADRs covering at least:
- Stack choice (see
mobile-tech-stack-selection).
- Minimum OS versions and the policy for dropping them.
- Architecture pattern -- MVVM, MVI, TEA, Redux, Clean, etc.
- Navigation approach -- coordinator, declarative router, stack-based.
- State management library -- Riverpod, BLoC, Redux Toolkit, Compose state, SwiftUI state.
- Networking layer -- URLSession, Retrofit, Ktor, Dio, fetch/axios, generated client.
- Persistence -- SQLite wrapper, Room, Core Data, Drift, SQLDelight, Realm.
- DI strategy -- constructor, Hilt, Koin, Riverpod, SwiftUI EnvironmentObject.
- Error model -- sealed error types, Result, exceptions, typed failures.
- Observability stack -- crash reporter, analytics, logging, performance.
- Feature flag system -- config service, build-time flags, remote config.
- Release strategy -- staged rollout percentages, kill switches, flavors.
- CI system and signing -- GitHub Actions, Bitrise, Codemagic, Xcode Cloud.
- Privacy boundaries -- what leaves the device and through which SDK.
3. How to Propose a New ADR
An ADR becomes mandatory when a decision:
- Affects more than one module or platform.
- Is expensive to reverse (migrations, data model, public API surface).
- Introduces a new runtime dependency.
- Changes the deployment or compliance surface.
Otherwise, a code comment or CODEOWNERS note is enough.
4. Decision Anti-Patterns
- Whiteboard-only decisions. Write them down, even a week late.
- Implicit decisions. "We are using X because it is already there" must still become an ADR if any of the triggers in Section 3 apply.
- Mega-ADRs. Split decisions so each can be superseded independently.
- Vague consequences. Name specific costs (binary size, startup time, team learning curve).
5. Example Matrix of Architectural Decisions per Stack
Use this to seed ADRs on day one. Adjust to the chosen stack.
| Concern | Native iOS | Native Android | Flutter | React Native | KMP |
|---|
| UI pattern | SwiftUI + MV | Compose + MVVM | Widgets + Riverpod/BLoC | RN + hooks + Redux/Zustand | Compose MP or native UI |
| Nav | NavigationStack | Navigation-Compose | go_router | React Navigation | expect/actual + platform nav |
| Async | async/await | Coroutines + Flow | Future / Stream | async/await + RxJS optional | Coroutines + Flow |
| Persistence | Core Data / SwiftData | Room | Drift / sqflite | WatermelonDB / SQLite | SQLDelight |
| DI | plain init + EnvironmentObject | Hilt / Koin | Riverpod / get_it | plain context / DI libs | Koin |
| HTTP | URLSession | Retrofit / Ktor | Dio | fetch / axios | Ktor |
| Errors | typed enums + Result | sealed class + Result | sealed unions (freezed) | discriminated unions | sealed class |
6. Keeping ADRs Alive
- Link the ADR index from the top of the README.
- Require an ADR reference in the PR template for any change touching the listed surfaces.
- Review ADRs quarterly; supersede anything that no longer matches reality.
- When onboarding, read the ADR index before reading code.
7. Example ADR Index Snippet
# Architecture Decisions
| # | Title | Status |
| --- | --- | --- |
| 0001 | Mobile stack: KMP + native UI | Accepted |
| 0002 | Minimum iOS 15 / Android 24 | Accepted |
| 0003 | Compose MVVM with unidirectional data flow | Accepted |
| 0004 | Networking via Ktor shared client | Accepted |
| 0005 | SQLDelight for persistence | Accepted |
| 0006 | Crashlytics + Sentry for releases | Accepted |
| 0007 | Coroutines + Flow async model | Accepted |
Checklist