diagram.mmd — flowchart
Offline Sync Workflow flowchart diagram

An offline sync workflow describes how a mobile app continues to function without network connectivity, queues local mutations, and reconciles state with the backend once a connection is restored.

Modern mobile apps are expected to remain usable on the subway, in airplane mode, or in areas with intermittent signal. The local-first architecture that enables this uses an on-device store (SQLite, Realm, Core Data, or a structured cache) as the primary source of truth for reads. Writes always go to the local store first and are also appended to a mutation queue — a persistent log of pending operations (create, update, delete) that haven't yet been confirmed by the server.

When a network connection is available, the app checks the mutation queue. If the queue is non-empty, a sync process dequeues operations in order and sends them to the backend API. For each operation the server accepts, the local record is updated with the server-assigned ID or any server-side field updates (timestamps, version numbers), and the entry is removed from the queue. If the server returns a conflict error — because another client modified the same record — the app applies a conflict resolution strategy: last-write-wins, server-wins, or a merge function specific to the data type.

Errors that are not conflicts (network timeouts, 5xx responses) leave the operation in the queue for retry. A backoff strategy prevents hammering the server during an outage. On app relaunch, the queue is reloaded from persistent storage so no pending changes are lost even if the app is killed.

For cache read strategies that complement offline writes, see Mobile Cache Strategy. For how background processes can run sync jobs without the user opening the app, see Background Job Execution.

Free online editor
Edit this diagram in Graphlet
Fork, modify, and export to SVG or PNG. No sign-up required.
Open in Graphlet →

Frequently asked questions

An offline sync workflow is the architecture that allows a mobile app to accept user writes when disconnected, persist them in a local mutation queue, and replay those mutations against the backend in order once connectivity is restored — keeping both the device and server eventually consistent.
When the server rejects a mutation because another client modified the same record, the app applies a conflict resolution strategy. Last-write-wins uses the latest timestamp; server-wins discards the local change; a merge function combines both changes at the field level. The right strategy depends on the data type and acceptable data loss risk.
Use offline-first when your users operate in low-connectivity environments — field workers, travellers, or users in areas with unreliable signal — or when any interaction delay due to network latency would significantly degrade the user experience. Note that conflict resolution complexity increases with the number of concurrent editors.
Failing to persist the mutation queue to durable storage means queued changes are lost if the app is killed. Not assigning client-side IDs to new records before syncing makes it impossible to correlate the local record with the server response. Processing the queue out of order can produce incorrect final state when later mutations depend on the outcome of earlier ones.
Last-write-wins keeps whichever mutation has the most recent timestamp, meaning a delayed offline mutation can overwrite a more recent online edit if its timestamp is newer. Server-wins always discards the local change when a conflict is detected, ensuring the server is always the source of truth at the cost of silently losing the client's offline work.
mermaid
flowchart TD A([User performs action]) --> B[Write to local store] B --> C[Append operation to mutation queue] C --> D{Network available?} D -- No --> E[Wait for connectivity change] E --> D D -- Yes --> F[Dequeue next pending operation] F --> G[POST operation to backend API] G --> H{API response?} H -- 200 OK --> I[Update local record with server response] I --> J[Remove operation from queue] J --> K{Queue empty?} K -- No --> F K -- Yes --> L([Sync complete]) H -- 409 Conflict --> M[Apply conflict resolution strategy] M --> N{Resolution outcome} N -- Server wins --> O[Overwrite local record with server version] N -- Merge --> P[Merge fields and re-send merged record] O --> J P --> G H -- 5xx / Timeout --> Q[Backoff and retry] Q --> D
Copied to clipboard