Skip to main content

Offline write strategies and optimistic UI

Choose per operation​

StrategyFlowAppropriate
online-onlyserver first, then localbank transfer/quote requiring live authorization
queuedenqueue, send latertelemetry/non-urgent fire-and-forget
lazy/local-firstlocal truth + outbox, sync laternotes/tasks/favorites/drafts

An app can be offline-first for reads while requiring online payment writes.

Transactional optimistic update​

database.withTransaction {
taskDao.updateTitle(id, newTitle, SyncStatus.Pending)
outboxDao.insert(
OutboxEntity(
operationId = UUID.randomUUID().toString(),
entityId = id.value,
kind = "rename_task",
payload = encode(newTitle),
)
)
}
scheduleSync()

Writing entity and outbox atomically prevents “UI changed but never synced” after crash. UI observes pending local value immediately.

Rollback is not always correct​

If server rejects favorite toggle, rollback is simple. If user edited a long note while offline, discarding it is unacceptable. Preserve local draft/conflict and ask user/merge. Product semantics decide.

Multiple local edits​

Before upload, collapse superseded operations when safe:

  • favorite true→false can coalesce to latest desired state
  • increment commands cannot always coalesce without semantics
  • append messages must preserve each item/order
  • create then delete before sync can cancel both if never externally visible

Use operation identity and base/server version. Do not mutate JSON payload blindly.

User-visible status​

Pending/syncing/rejected/conflicted should be visible where consequences matter. “Saved” might mean saved locally; communicate when cloud backup/team visibility is pending.

Undo​

Undo before remote commit can cancel/replace pending operation transactionally. After commit, undo is a new compensating operation, not history erasure.

Security​

Outbox payload is persisted sensitive data. Minimize fields, encrypt if threat model requires, expire on logout/account removal, and never log full payload.

Optimistic is not imaginary

Optimistic UI should reflect a durable local state transition with pending metadata—not a ViewModel-only visual guess that disappears after process death.

Exercises​

  1. Choose write strategy for transfer, favorite, analytics, and note edit.
  2. Coalesce safe outbox operations.
  3. Design undo before and after remote commit.