Offline-First Architecture Quiz

DATA › Offline

In a correctly designed offline-first app, where do the UI and domain layers read data from?

Answer: From the repository, which reads the local source of truth.

Higher layers talk only to the repository, which reads from the local store; network responses are written to local first so reads always reflect one canonical source.

Which write strategy is most appropriate for a bank transfer that must not be applied unless it reaches the server?

Answer: Online-only write

Online-only writes go to the network first and only update local on success, surfacing failures immediately, which is required for time-sensitive operations that must succeed remotely.

What does the stale-while-revalidate approach prioritize?

Answer: Show cached data instantly, then refresh in the background

Stale-while-revalidate serves the cached value immediately for responsiveness, then fetches fresh data and updates the cache so observers re-emit the new state.

Why is WorkManager preferred over a plain ViewModel coroutine for background sync?

Answer: It survives process death and reboots, with constrained retryable work

WorkManager schedules durable, constraint-aware work that survives process death and reboot, with automatic exponential-backoff retries, which a ViewModel coroutine cannot guarantee.

A SyncWorker (CoroutineWorker) fails to reach the server due to a transient error. What should doWork() return?

Answer: Return Result.retry() so WorkManager retries with backoff

Returning Result.retry() tells WorkManager to reschedule the work using its exponential-backoff policy, the correct response to a transient/recoverable failure.

What is a key limitation of a simple last-write-wins conflict resolution strategy?

Answer: It can silently drop a concurrent edit, keeping only the newest write

Last-write-wins keeps only the newest write by timestamp, so a competing concurrent change can be overwritten and lost without the user being aware.

Which WorkManager constraint ensures a sync job only runs once the device has network connectivity?

Answer: setRequiredNetworkType(NetworkType.CONNECTED)

Adding a NetworkType.CONNECTED constraint defers the work until connectivity is available; charging, idle, and expedited options control unrelated scheduling behavior.

Which scenario is the best fit for a lazy (local-first) write strategy?

Answer: Editing a note that must never be lost, with instant UI and background sync

Lazy writes update the local store immediately and queue the network sync, giving instant UI feedback while protecting critical user-authored data, which suits an edit that must not be lost.

What is the role of Jetpack Paging's RemoteMediator in an offline-first paged list?

Answer: It loads network pages into Room, and Paging serves from that cache

RemoteMediator is the pull-based bridge that loads network pages into the local database; Paging then reads from that cache, so already-loaded pages remain available offline.

For an app that is offline for long stretches and syncs relational data, which synchronization model is generally more suitable?

Answer: Push-based: seed a baseline, then react to change signals with versioning

Long offline periods and relational data favor a push model that establishes a baseline and reacts to change signals with versioning, rather than repeatedly pulling on demand.

An exception is thrown while collecting a Room Flow. How should the repository or ViewModel handle it so the UI does not crash?

Answer: Use catch on the Flow and emit an error UI state like LCE Error

The catch operator intercepts upstream exceptions and lets you emit an error UI state (commonly an LCE sealed type), keeping the stream alive instead of propagating a crash.

Why should each queued offline write carry a client-generated unique ID (such as a UUID) when it is eventually sent to the server?

Answer: So the server can spot a retried write and skip applying it twice.

A stable client-supplied ID lets the server deduplicate retried requests, so a write that succeeded but whose response was lost is not applied a second time on retry.

How do you prevent overlapping or duplicate periodic sync jobs from being enqueued every time the app starts?

Answer: Use unique work with a stable name and ExistingWorkPolicy.KEEP

Enqueuing unique work with a stable name and a policy like KEEP ensures WorkManager coalesces requests so only one sync chain for that name exists, avoiding duplicates.

When syncing deletions in an offline-first app, why is a soft-delete (tombstone) often used instead of immediately removing the row locally?

Answer: It marks the item deleted so sync can send it and prevent re-creation

A tombstone preserves the intent to delete so the sync layer can push it to the server; a hard local delete would leave no record and a later pull could re-create the row.

Back to Offline-First Architecture