Design an Offline-First Client That Syncs Edits and Resolves Multi-Device Conflicts
Company: Google
Role: Software Engineer
Category: System Design
Difficulty: medium
Interview Round: Onsite
Design the client-side part of a system in which users edit data. The network is unreliable, so a user must be able to keep editing while the connection is poor or absent. Every edit must be saved in local storage on the device as it is made, and when the network recovers, the client must synchronize the saved edits with the server. The same data may be changed from more than one device, so the client must also detect and handle version conflicts.
Concentrate on the client: how it stores data and edits, how and when it talks to the server, and how it deals with conflicts. Describe the server only as far as the client depends on it, such as the sync API and the versioning it provides.
### Constraints and Clarifications
- Edits must work, and must persist on the device, with no network connection.
- Synchronization happens when connectivity returns; the user should not have to trigger it by hand.
- Several devices can modify the same piece of data, so two edits to the same item may both be based on the same older version.
- The kind of data, the conflict policy and the server API are not specified; settle them with the questions below and state your assumptions.
### Clarifying Questions
- What is being edited: small structured records such as forms, settings or task items, or long free-form documents in which two edits can touch the same sentence?
- Are the conflicting devices always one user's own devices, or can different users share and edit the same data?
- Should conflicts be resolved automatically, or does the product want the user to choose in some cases?
- Which platforms does the client run on, and roughly how much data does one user keep on a device?
- How long can a device stay offline, and is it ever acceptable to discard edits made offline?
- Does the server's API already exist, or can the client design shape the sync protocol?
### Part 1 — Local storage and offline edits
Describe how the client stores data on the device and records the user's edits so that the UI responds immediately, edits survive an app restart or crash while offline, and no edit is lost before the server has it.
```hint Two kinds of local state
Consider keeping what the screen shows separate from the record of changes the server has not yet acknowledged, and ask how both stay consistent if the app dies in the middle of an edit.
```
#### What This Part Should Cover
- The local data model for items and for pending edits
- How an edit is applied locally and recorded atomically
- Durability across restarts, and many edits to the same item while offline
### Part 2 — Synchronizing when the network returns
Explain what the client does when connectivity comes back or keeps dropping: when it starts syncing, how it sends pending edits, how it receives changes made on other devices, and what the requests and responses look like.
```hint Assume the response can be lost
A request may reach the server and change its state even though the client never sees the reply. Work out what makes resending the same edits harmless.
```
#### What This Part Should Cover
- Sync triggers, retries and backoff
- A push and pull protocol with its ordering and duplicate-safety guarantees
- Applying incoming changes without overwriting the client's own unsent edits
### Part 3 — Version conflicts across devices
Two devices edit the same item while at least one of them is offline. Explain how the conflict is detected, how it is resolved, and what the user experiences.
```hint Remember what each edit was based on
An edit is only in conflict relative to the version of the item it started from. Decide what the client must keep so that the server, or the client, can tell the two apart and reconcile them.
```
#### What This Part Should Cover
- The detection mechanism, and why it does not depend on device clocks
- A resolution policy suited to the data, with at least one alternative weighed
- Edit-versus-delete conflicts, and what the user sees when a conflict cannot be resolved automatically
### What a Strong Answer Covers
- A local-first architecture in which the UI reads and writes only local state and a separate sync component talks to the server
- Every edit taking effect on the server exactly once despite crashes, retries and lost responses
- Concrete API shapes, version or cursor fields, and the client's handling of each kind of response
- Failure modes beyond the happy path: permanently rejected edits, expired credentials while offline, local storage limits and local schema upgrades
- Client-side signals for monitoring sync health
### Follow-up Questions
- The edited data turns out to be long text that two people change at the same time while offline. Does your conflict approach still hold, and what would you switch to?
- A device stays offline for weeks and accumulates thousands of edits. What happens to local storage, to the size of the first sync, and to the pull of other devices' changes?
- The server changes its data format while some clients still have old-format edits queued. How do those edits reach the server safely?
- How would you test the sync engine so that a crash or a dropped connection at every step is covered?
Overview: Design the client side of an app where users keep editing data offline, store every edit locally, and sync with the server when the network returns. Covers the local data model and edit queue, a sync protocol that is safe to retry, and detecting and resolving version conflicts when several devices change the same data.