Mobile system design · 17 min
Mobile system design interview: how the round is scored
How a mobile system design round runs, the seven things a senior answer covers, a worked offline sync example, and how Senior and Staff are scored.
Mobile system design · 14 min read
How to design offline-first sync in a mobile system design interview: local source of truth, the outbox, conflict rules, clocks and migration on device.
This guide is for Senior and Staff mobile engineers who know how the system design round runs and want to be ready for offline-first mobile system design, the scenario the round keeps turning into: data that must work without a network and sync later. It covers what a strong answer says about the source of truth, the outbox, idempotency, conflicts, clocks and schema migration on device, with a worked design for a field inspection app and the follow-up questions the round asks, each with the answer that scores.
The general round and a simpler worked example (offline notes) are in the mobile system design interview guide. This page goes deeper, on a harder scenario.
Whatever the prompt, chat, a feed, a to-do list, a delivery app, the interviewer will eventually take the network away. It is the fastest way to find out whether your design has a source of truth, whether writes survive the process being killed, and whether you have a rule for two devices disagreeing.
The recurring weak answer is a cache. “We store the last response and show it offline.” That makes reads work offline. It says nothing about writes, which is where the design is tested.
Offline-first is a promise the product and the sync protocol both have to keep. A cache does not make an app offline-first. Useful work happens locally, the server’s authority is explicit, every write is durable before the user is told it succeeded, and the devices eventually converge. If your answer does not cover all four, it is not offline-first yet.
Split the problem in two before you draw anything. Showing data without a network and accepting changes without one fail in different ways, so treat them as two problems.
Say both invariants out loud, separately. A design where only reads work offline is incomplete, however good the list screen looks.
The write path is where the round is won, and the order of operations is the whole point:
URLSession for uploads on iOS.Get that order backwards, a confirmation rendered from UI state while the upload is still in flight, and a process kill loses the work while the screen said “saved”. That is the bug this whole design exists to prevent.
Two details separate a senior answer here:
The interviewer’s next move is usually the same: “Two devices edit the same record while offline. Both come online.”
The senior move is to make conflict policy per field, not per database. The same sync engine can carry data where a lost edit is an annoyance and data where it is a safety or money problem.
| Policy | When it is right | What it costs |
|---|---|---|
| Last write wins, ordered by the server | Free text where a lost keystroke is acceptable | Silent loss of the other edit |
| Keep both | Documents where no automatic merge is safe | User friction, a simple build |
| Field-level merge | Records whose fields are edited independently | Needs per-field versions |
| Ask a person | Values where a wrong automatic choice is dangerous | A review state and a UI for it |
| CRDT | Real-time collaboration on the same content | The highest complexity; rarely justified in version one |
Then separate detection from resolution. Detection is mechanical: two writes target the same record and neither was based on the other’s version. It belongs to the sync layer and is the same for every data type. Resolution is domain policy, and it belongs to the people who understand what a conflict costs. A design that fuses the two tends to reach for “just re-download everything” as its answer to every confusing conflict, which is expensive on a bad connection and still resolves by accident.
Device clocks are wrong, sometimes by minutes. A design that orders offline edits by device timestamp will, at some point, keep the older value. Walk through it in the interview: one device’s clock is fast, its earlier edit carries a later timestamp, and last-write-wins silently keeps the wrong one.
What to use instead:
The follow-up: “You need to change the schema. What happens to users on the old version?” This is a Staff question. Senior and Staff candidates usually draw the same boxes. The difference shows in how they handle migration, several app versions live at once, and backing a change out.
Three things are true on a phone that are not true on a server:
The shape that survives interruption is expand, migrate, contract, spread over several releases. Expand: add the new table, keep the old one, write to both. Migrate: backfill in the background in small batches, each batch committing its rows and a progress watermark in one transaction, so a killed process resumes where it stopped. Contract: drop the old structure in a later release, once telemetry shows the backfill finished for that cohort. The trap is one large transaction around the whole migration because it feels safe. On SQLite it holds the write lock throughout, grows the journal on a phone that may be nearly full, and a kill rolls all of it back, so the user starts from zero on every launch. Users on much older schemas also update straight to the newest, so every step must compose and resume.
A strong answer names the transition state, not only the start and end state: which versions coexist, what the server accepts from each, who owns the temporary compatibility code, and the condition under which it is removed (“when the old version falls below a threshold of active devices”). The Staff mobile system design guide covers why migration and ownership separate Staff answers from Senior ones.
The prompt: “Technicians inspect equipment at remote sites, often underground with no signal. They fill in a checklist, record readings and take photos. Design the app.”
Requirements worth asking about. Can two technicians inspect the same asset on the same day? (Yes.) How large are the photos? (Several megabytes each.) How stale may the job list be? (Same-day reassignment is rare.) Is there a regulatory record at the end? (Yes, so the server decides what is accepted.) Are the devices managed, so some cannot update? (Assume yes.)
The design, in the order a strong answer gives it:
What the interviewer writes down is not the boxes. It is that the confirmation depends on a committed transaction, that the key is minted on the device, that conflict policy differs by field, and that old versions were part of the plan.
| Question | Answer that scores | The trap |
|---|---|---|
| “The app is killed right after the user taps Save.” | The write and the outbox row were committed before the confirmation, so nothing is lost; the worker sends it on the next opportunity | Saying the upload “retries” when the retry lived in the killed process |
| “The request timed out. Did the server get it?” | You do not know, so you resend with the same device-minted idempotency key and the server deduplicates | Generating a new request id on retry |
| “Two devices edited the same record offline.” | Detection by version, resolution by field policy; name which fields merge and which go to review | Last write wins by device timestamp |
| “Why not order by timestamp?” | Device clocks drift; order by a server-assigned version | “We sync clocks with NTP” |
| “A user deleted an item, another device was offline for a month.” | Tombstones kept longer than the longest realistic offline window | Deleting the row on the server immediately |
| “How do you sync in the background every few minutes?” | Neither platform guarantees a schedule; sync on foreground, on connectivity, and opportunistically in the background | Promising a fixed interval |
| “The outbox has a 40 MB video in front of a 2 KB form.” | Separate lanes for critical records and bulk uploads | One FIFO queue |
| “The session expired while items were queued.” | Refresh the credential without changing who authored the item; escalate when the author cannot be re-authenticated | Sending queued items under whoever is logged in now |
| “You changed the schema. What about users on the old version?” | Name the transition: both shapes accepted, an owner for the compatibility code, a removal condition | Assuming everyone upgrades |
| “The migration takes minutes on some phones.” | Small batches that commit a durable watermark; expand, migrate, contract across releases | One transaction around the whole migration |
| “How do you know it works in production?” | Offline completion rate, outbox age, convergence time, permanent failures, by app version | “We look at crash reports” |
Use the table as a drill: cover the middle column, answer each question out loud, then check what you left out. The trap column is what the interviewer is listening for.

Mobile system design · 17 min
How a mobile system design round runs, the seven things a senior answer covers, a worked offline sync example, and how Senior and Staff are scored.

React Native · 14 min
Twelve React Native interview questions on rendering, lists, effects, the New Architecture, Hermes and storage, with what is scored, the trap and the follow-up.

Senior and Staff loops · 15 min
How I decide Staff vs Senior in a mobile system design loop: the questions I ask, what each level answers, the follow-ups, and how down-levelling happens.