Offline-first architecture
Offline-first mobile architecture
Offline-first is a product consistency decision, not a cache toggle.
Mobile System Design Blueprint (book, from $199)
Offline-first architecture: what matters most
Offline-first mobile architecture makes durable local data the immediate source of truth and synchronises it with the server under explicit consistency rules. The design must distinguish cached reads from pending user writes, assign stable identifiers, make writes idempotent and expose synchronisation state to the UI. Conflict policy depends on the domain: last-write-wins may suit preferences, while collaborative edits or financial actions require stronger rules.
Background execution should improve freshness but cannot be the only path to correctness. A design that holds up survives retries, duplicate delivery, clock drift, schema migration and app termination. The user should know when data is saved locally, pending remotely or blocked by a conflict.
Choose the source of truth
If screens read from both network responses and a database, state can diverge. Prefer one observable local model and let synchronisation update it.
I named a chapter of Controlled Change after this: offline-first is a product decision, a contract about continuity and truth, not a cache strategy.
- Durable local entities
- Pending mutation metadata
- Server version or revision
- Last successful synchronisation
- Conflict and failure state
- Migration version
Design writes as a state machine
A write moves from local intent to queued, sending, acknowledged or failed. Retrying must not duplicate the action, and permanent failure needs a visible recovery path.
Separate safe automatic retries from actions that require the user to decide again.
Offline-first architecture on Android and iOS
Offline-first is not local-first. Offline-first keeps the server as the authority and syncs the device to it; local-first treats the copy on the device as primary and the server as one more replica.
The design is the same on both platforms and the mechanisms differ. On Android, a local database such as Room is the observable source of truth, and WorkManager runs deferrable sync under constraints such as network availability. On iOS, a local store such as SQLite, Core Data or SwiftData plays that role, and background tasks run when the system grants time, not when the app asks.
On neither platform is background execution a guarantee, so sync also runs at launch, on return to the foreground and after user actions. What background sync can promise on iOS and Android goes through the limits of each.
Test the ugly timeline
Test app termination during a write, an old device reconnecting, token expiry, reordered responses and schema changes while the queue is nonempty.
These timelines reveal whether offline-first is real or only a successful-demo path.