A mobile connection can disappear between pressing Save and receiving a response. Offline support therefore needs a product decision: what can the user read, what can they change, and how will the application explain work that has not reached the server?

Begin with one read flow

Flutter's offline-first guidance places local and remote data coordination in a repository. A practical reading flow can show cached content first, then refresh it. Decide how old content may be, whether a refresh failure should block reading, and how the user can recognize outdated information.

For an article list, yesterday's cache may be useful. For stock availability at checkout, it may be misleading. Define freshness per feature, not as one application-wide number. Store a successful synchronization timestamp separately from the time a screen was opened.

Treat queued writes as a real workflow

A queued edit needs a durable operation identifier, a target record, a payload, and a visible status. The backend must be able to recognize duplicates if the same operation is retried. “Saved on this device” and “Synchronized” should have different meanings in the interface.

  • Pending: recorded locally and waiting to send.
  • Sending: currently being attempted.
  • Failed: needs retry or user attention.
  • Confirmed: acknowledged by the server.

These labels are a design example, not a required database schema. The important part is that leaving the screen or restarting the app does not quietly discard work the user was told had been saved.

Choose a conflict policy

If two devices edit a note, the later timestamp does not automatically identify the user's intended version. A simple product may accept server-wins or last-write-wins, while a collaborative product may need merging or an explicit conflict screen. Document the loss tradeoff and preserve enough information to explain it.

Test broken connections deliberately

Test launch without connectivity, loss during upload, reconnection after several edits, account switching with pending work, and process termination after a local save. Also test an expired session while reconnecting. A connectivity indicator alone cannot prove that the API is reachable or that an authenticated write will succeed.

Make the first offline feature small enough that you can explain every transition. Once the behavior is trustworthy, reuse the policy for other flows with similar data.

Official reference: Flutter offline-first support.