Skip to main content
O
OSTORDEV

Offline-First Mobile Apps: Sync, Conflict Resolution, and Honest UX

Field teams and travelers expect apps to work without perfect connectivity. Here is how we design local storage, sync, and conflict resolution for React Native and Flutter apps.

By OSTORDEV Engineering TeamPublished Updated 4 min read
Illustration of a mobile phone syncing data after reconnecting to the network

Key takeaways

  • Offline-first means the app reads and writes to a local database first and syncs with the server in the background.
  • Pick storage by access pattern: SQLite-based databases for structured data, encrypted storage for secrets, and the file system for media.
  • Queue every change as an operation with a unique ID so retries never create duplicates.
  • Define conflict rules per data type: last-write-wins, field-level merges, or server decisions for money and inventory.
  • Show sync status honestly so users always know what is saved on the device and what has reached the server.

What is an offline-first mobile app?

An offline-first app treats the network as an enhancement, not a requirement. Every screen reads from data stored on the device, every action writes locally first, and a sync engine exchanges changes with the server whenever a connection is available.

Offline is not an error state; it is daily reality for technicians in basements, sales reps on the road, travelers, and users in areas with patchy coverage. Designing for it from the start is far cheaper than retrofitting it after launch, which is why our mobile app development projects decide on offline requirements during discovery.

When does an app need to work offline?

Not every app needs full offline support. We recommend it when:

  • Users work in the field, in warehouses, on construction sites, or while traveling.
  • Losing a form or an order because the signal dropped would cost real money.
  • The app is used in regions where mobile data is slow or expensive.
  • Speed matters: reading from a local database makes screens feel instant even online.

For content-only apps, a simpler cache of recent data is often enough.

How do you choose local storage?

Local storage choice depends on access patterns, not fashion:

  • Structured, relational data such as orders, tasks, or customers: an embedded SQLite-based database, used directly or through libraries like WatermelonDB or op-sqlite in React Native and Drift in Flutter.
  • Secrets and tokens: the platform keychain or keystore, never plain key-value storage.
  • Photos and documents: the file system, with metadata in the database and clear eviction rules so devices never run out of space silently.

We encrypt sensitive local data at rest and plan migrations from the first release, because schema changes on thousands of devices cannot be rolled back.

How should data sync work?

A reliable sync engine has two directions. Push sends local changes to the server; pull fetches changes made elsewhere since the last successful sync, usually with a cursor or timestamp.

  1. Record each user action as an operation in a local outbox, with a unique client-generated ID.
  2. Apply the change to the local database immediately so the UI updates.
  3. Push outbox operations in batches when online; the server uses the IDs to ignore duplicates, making retries safe.
  4. Pull remote changes and merge them, then advance the sync cursor.

Batching and compression save battery and data. The backend must be designed for this pattern too, with idempotent endpoints and change feeds; our cloud & DevOps team builds APIs that support it.

How do you resolve sync conflicts?

Conflicts happen when two devices edit the same record before syncing. There is no universal answer, so we document a rule per data type:

  • Last-write-wins for low-stakes data like user preferences.
  • Field-level merge when different people usually edit different fields of the same record.
  • CRDTs or operational transforms for collaborative text and lists.
  • Server adjudication for money, stock levels, and bookings, where the server checks business rules and may reject a change.

How should retries and background sync behave?

Networks fail in messy ways. We retry with exponential backoff and random jitter, so thousands of devices reconnecting after an outage do not overwhelm the server at the same moment. Background sync respects platform limits on iOS and Android, and we surface a manual retry when user confirmation is safer than silent loops.

What does honest offline UX look like?

The interface should never pretend something reached the server when it did not. We design a single sync-status model that every screen uses:

  • A subtle indicator for offline mode, not a blocking error.
  • Per-item states: saved on device, syncing, synced, or needs attention.
  • Clear messages when an action truly requires a connection, such as a card payment.

Our UI/UX design team designs these states alongside the happy path, not as an afterthought.

How do you test an offline-first app?

We test with network conditioning on real devices, toggle airplane mode mid-action, kill the app during sync, and run two devices editing the same record. Automated tests cover the sync engine and conflict rules, and crash and sync-failure metrics are monitored after release as part of maintenance & support.

The same principle behind fast websites applies here: perceived speed comes from not waiting on the network, a theme we also cover in our Next.js performance guide. If your roadmap includes field teams, retail, or emerging markets, talk to us early.

Frequently asked questions

Can React Native apps work offline?

Yes. React Native apps can store data in an embedded SQLite-based database, queue changes locally, and sync in the background, giving a full offline experience on iOS and Android.

Is Flutter or React Native better for offline-first apps?

Both are capable. The architecture matters more than the framework: a local database, an outbox of operations, idempotent APIs, and clear conflict rules. Choose the framework that fits your team.

What is the best database for an offline mobile app?

For structured data, an embedded SQLite-based database is the most proven option on both platforms. Store secrets in the keychain or keystore and large files on the file system.

How do you handle conflicts when two users edit the same data offline?

Define a rule per data type: last-write-wins for preferences, field-level merges for shared records, CRDTs for collaborative text, and server-side validation for money or inventory.

OSTORDEV Engineering Team

Senior engineers at OSTORDEV, a web, mobile, and AI development agency in Casablanca, Morocco. We write about problems we solve in client projects.

Keep reading

Have a project in mind?

Tell us what you are building. We reply within one business day with next steps.

Discuss a project