Mobile System Design Interview

Course Content

Mobile System Design Interview

11 sections · 23 lessons

The framework: client architecture, data flow and the closing fifteen minutes


Steps 3 and 4 are the two ten-minute blocks in the middle of the round, and they are where the marks are. Step 3 is the diagram you draw in every mobile system design interview: learn one shape, then change the labels for each problem. Step 4 says how a change moves through that shape, and it is where a design is either coherent or a collection of boxes.

Then the last fifteen minutes — the deep dive, the constraint sweep and the edge cases — decide whether a competent answer becomes a strong one. This lesson covers all four.

Step 3: three layers

Presentation. Screens and the objects that hold their state. Its rule: it knows nothing about the network, the database, or where data came from. It asks for data and renders what it gets.

Domain. The application's actual rules — validation, what a "conflict" means, when a draft becomes a message. On small features this layer is thin or absent, and saying so is better than inventing ceremony for it.

Data. The repository, plus the two things underneath it: a local store and a remote data source. The repository is the important box.

The repository, and why it is the answer to most questions

A repository exposes data to the layers above it and hides where that data came from. It is the single source of truth: one place that decides what "the current feed" is, so two screens showing the same post cannot disagree.

The rule that makes offline work is a property of this box: the repository reads from the local store and writes network results into it. Callers get local data, always. The network is a background process that keeps local data fresh.

UI layerviews, state holdersDomain layeruse cases, business rulesRepositorythe single source of truthLocal storeSQLite / Room / Core DataRemote data sourceHTTP clientBackend APInetworkwhat the repository is forThe UI never knows whether data came from disk or the network.It decides the caching policy in one place.It is the only layer that has to be tested against a flaky network.Swapping the backend touches one file, not every screen.the arrow the interviewer checks: if the UIcan reach this directly, the layering isdecorativeDependencies point downward only. Data flows back up as observable state, so a cache writerefreshes the screen without the screen asking.
The repository exists so that "where did this data come from" is answered in one file rather than in every screen.

Naming, and not arguing about it

Every platform has its own name for the presentation pattern. Say which one you would use, in one sentence, and move on: "I'd use whichever unidirectional presentation pattern the team already uses — the architecture below the presentation layer is the same either way."

Spending three minutes defending one pattern over another is a poor use of the round. The interviewer is checking that layers exist and are respected, not adjudicating a naming dispute.

Step 4: data flow and state

Layers say what exists. Data flow says how a change moves through them.

One direction, and the store in the middleUser actionViewModel intentRepository writeLocal storeState to UIThe screen never reads the network directly; it observes the store, which the network updates.
Writing to the store first is the single rule that makes the same code path work offline.

Unidirectional data flow

Data moves in one direction round a loop: an event goes down, a change is written, new state comes back up, the screen re-renders.

Text
user taps "like"  → screen emits an intent  → state holder calls repository.like(postId)  → repository writes to local store: liked = true, pending = true  → local store emits a change  → repository's stream emits new state  → screen re-renders with the heart filled  ... separately, the outbox drains to the network,      and clears `pending` (or reverts on permanent failure)

Nothing skips a step and nothing flows backwards. That property is what makes the app debuggable: any wrong pixel is traceable to a write in the local store.

The naive alternative — the screen calls the network, gets a response, and updates itself directly — produces two problems immediately. Two screens showing the same post disagree, because each has its own copy. And the change is lost when the process is killed, because it was never written anywhere.

The rule that makes offline work

Say this out loud in the interview. It is short, it is the correct answer to a large class of follow-up questions, and it tells the interviewer that the architecture you drew was not decoration.

Where state lives, in four tiers

TierLifetimeExamples
Ephemeral UI stateUntil the screen closesScroll offset, text being typed, whether a sheet is open
Screen stateSurvives rotation and short backgroundingThe list being displayed, the selected filter
Persisted app stateSurvives process deathFeed rows, messages, drafts, the outbox
Server stateShared across devicesEverything the account owns

The tier that gets forgotten is the third. A user filling in a booking form, backgrounded while they check an email, returns to an empty form because the draft lived in memory. Client architecture for a multi-step flow designs around exactly that.

Process death, and the honest way to talk about it

Process death is not an edge case — it is routine. The operating system reclaims backgrounded apps under memory pressure many times a day. When the user returns, the app is relaunched from scratch and must reconstruct the screen they were on.

What must survive: where they were, what they had typed, and anything they had done that has not reached the server. What need not: caches, in-flight requests, and anything derivable.

Steps 5–7: depth, constraints, and edge cases

With the architecture and the data flow on the board, you are at about minute thirty. The last fifteen minutes decide whether a competent answer becomes a strong one.

Spending the last fifteen minutesPick one deep diveName the six constraintsWalk the edge casesClose with trade-offs
A competent answer becomes a strong one in the final third, where depth and constraints are demonstrated rather than promised.

Step 5: the deep dive

Around minute thirty the interviewer picks a component and asks for detail. If they do not pick, offer two and let them choose: "I could go deep on the sync engine or on scroll performance — which is more useful?"

Going deep means four things, and shallow answers usually miss the last two:

  1. The data structures. Actual tables, actual fields, actual indexes.
  2. The algorithm. Stepped through with a concrete case, not described in the abstract.
  3. The failure cases. What happens when this component's assumptions are violated.
  4. The numbers. How big, how often, how long, how much memory.

If you have a choice, pick the component with an interesting offline or concurrency story. A sync engine, an outbox, or an update-coalescing pipeline gives you more to say than a list-rendering path — unless the interviewer has signalled they care about rendering, in which case they have told you the answer.

Step 6: the six constraints

Cover all six, briefly, out loud. One sentence each is enough, and omitting one is noticed.

ConstraintThe sentence
Network"Reads come from the local store, so the app works with no network; writes queue in the outbox."
Battery"We batch requests and drop to push when backgrounded, because radio wake-ups cost more than payload size."
Memory"Images are downsampled to display size at decode time; the list recycles views."
Storage"The cache has a ceiling of N MB, evicted least-recently-used, and the user can clear it."
Background limits"Sync is a deferred job, so it may not run for hours; nothing time-critical depends on it."
Process death"Screen position, drafts, and the outbox are persisted, so a relaunch restores the user's place."

Six sentences, roughly ninety seconds. It is the cheapest block of marks in the round.

Step 7: edge cases and the close

Pick two or three that are specific to this problem rather than generic. The strongest ones are usually:

  • The first launch with an empty database and no network.
  • The very large case: a user with 50,000 items, an account with a two-year backlog.
  • Concurrency: the same entity changed on two devices, or by a push while the user is editing it.
  • Permissions revoked — notifications, storage, location — after the feature was built assuming them.

Then close in two sentences: what you would build first, and what you would measure to know it works.