Not every offline-first pattern survives contact with real field conditions. After building three production apps with hard offline requirements — basement inspections, rural property valuations, site surveys — here's the architecture that actually holds.
The naive version of offline support is: store data locally, upload when connected. This works until two field workers edit the same inspection record, or a user submits data on a train and the request fires and fails five times before the connection stabilises.
Real offline-first is a distributed systems problem living inside a mobile app. You have eventual consistency, conflict resolution, queue management, and state synchronisation — all of it invisible to the user, all of it required to be correct.
The storage layer choice shapes everything else. My current default is SQLite via op-sqlite (fastest native SQLite wrapper for React Native) with a typed schema defined in TypeScript. WatermelonDB is worth considering for teams with complex relational data; MMKV is excellent for preferences and session state but not for structured data.
Define your schema before you write any sync code. The schema is your contract between the local store and the server. Changing it in production is painful — migration paths need to work in both directions and survive interrupted upgrades.
Simple key-value state → MMKV. Structured records with relations → SQLite. Complex sync with many-to-many relations → WatermelonDB. Don't use AsyncStorage for anything beyond trivial preferences.
You will have conflicts. Plan your resolution strategy before you see one, not after. The options:
In the property inspection app, we used LWW for 95% of fields and manual merge for three specific compliance fields. The mixed strategy was right — don’t apply manual merge everywhere because you’ll exhaust your users.
Build your sync engine as an explicit, observable state machine. States: idle → queuing → syncing → complete | error. Make state transitions logged events. Make the queue inspectable from a debug screen. You will need to debug this in the field.
Key requirements: idempotent operations (every write must be safe to retry), exponential backoff with jitter, and a dead-letter queue for writes that fail repeatedly. Never silently drop a failed write — route it to the dead-letter queue and alert the ops team.
On-device validation is the feature that made the property inspection app’s zero-lost-submission record possible. When a field worker submits an incomplete record with no signal, the validation runs locally and blocks submission with a clear error. They fix it before leaving the site.
Implement two validation layers: client-side for UX (immediate feedback) and server-side for correctness (authoritative). The client layer should replicate the server rules — use a shared validation schema if your architecture allows it.
This is what most offline-first guides skip. How do you know your sync engine is healthy in production? How do you know events aren’t silently queuing forever on some user’s device?
Instrument the sync engine as thoroughly as the rest of your app. Emit events for queue depth, sync duration, conflict count, and dead-letter entries. Set SLOs: P95 sync latency under 10s for a typical queue, dead-letter entries under 0.1% of total writes. Alert when you breach them.
Offline-first apps are harder to support. When a user reports missing data, the first question is “was it queued, synced, or dropped?” You need tooling to answer that question in seconds, not hours.
Build a support dashboard that shows per-user sync history, queue depth, and last-seen timestamps. It sounds like overhead — it pays for itself the first time you diagnose a data loss report in three minutes instead of three hours.
The goal isn’t to make offline work. It’s to make your team confident that offline is working — which requires observability, not just code.
Free 30-min data audit · No prep needed · Actionable gaps
5-Step Mobile Analytics Guide
Get the free checklist. Find out if the data behind your product decisions is complete — or if your app is quietly missing key user actions.
The guide is on its way — check your spam folder if it doesn't arrive within a minute.
Sent to:
The most common gap I find: key user actions tracked in the app but never arriving clean. Step 2 in the guide shows exactly where.
Book a free 30-min call and I'll go through your specific setup with you.
Schedule a free call →5-Step Mobile Analytics Guide
Leave a comment