Senior Engineering Interview Handbook / Chapter 139
Mobile Engineering
A specialty-track chapter for mobile engineering interviews, covering overweighted signals, likely round variations, foundations, prompts, red flags, preparation adjustments, and field reference.
Page tools
The phone dies after Submit
Imagine a mobile system-design prompt:
Field inspectors complete reports in places with unreliable connectivity. A
report contains structured answers and several photographs. Users sometimes
tap Submit, put the phone away, and later discover that the report never
arrived. Redesign the flow.
The tempting answer is “upload in the background.” That is not yet a design. The operating system may suspend the application, terminate its process, limit background execution, or reclaim cached files. The network may disappear after the server accepts the report but before the client receives the response. A photograph may upload while its metadata fails. The user may install a new app version before the pending work resumes. Battery and data-saving policies may delay work even when connectivity exists.
The interview is asking what Submit entitles the user to believe under those conditions. Mobile engineering begins where continuous process ownership ends.
This is the distinction a mobile loop tends to overweight. Platform fluency matters, but naming a background-task API, database, or cross-platform framework does not settle the promise. The candidate has to connect lifecycle, local state, remote authority, resource limits, release lag, and recovery.
Give “submitted” a precise meaning
Before drawing components, clarify the product contract. There are several defensible promises:
- saved on this device means the report can survive navigation and process death, but has not necessarily reached the service;
- pending submission means durable local work exists and the app will make bounded attempts under stated conditions;
- received means the server has durably accepted a particular submission;
- complete means the server has accepted the report and every required attachment, and any downstream validation has reached a defined outcome.
Those states must not share one success label. A spinner that disappears when the app backgrounds, or a green check based only on queue insertion, converts system uncertainty into false confidence.
The local store should contain enough truth to reconstruct the work after the process disappears. For this prompt that might include the report draft, stable references to locally controlled photo files, a submission operation ID, the base server version if an existing report is being changed, the state of each attachment, bounded retry metadata, and the last server acknowledgment. The UI is a projection of that durable state; it is not the only copy of it.
The server owns a different truth. It decides whether the caller is authorized, whether the report satisfies canonical rules, whether an operation has already been accepted, and which version is current. Local durability protects the user’s work. It does not make the device authoritative for shared or regulated records.
Follow one report through interruption
The smallest useful model has a durable report, durable attachment records, and a durable submission operation. A trace makes the ownership visible:
offline; report R is an editable local draft
user captures photo P
write P to app-controlled durable storage
commit {report: R, attachment: P, state: local} to the local database
user taps Submit
validate what can be checked locally
commit {operationId: O, report: R, state: pending} before network work
UI says “Pending submission,” not “Submitted”
network returns
create or resume the server submission using O as the idempotency key
transfer P through a resumable attachment session
persist each server acknowledgment locally
operating system terminates the process
no in-memory callback is required for correctness
application starts later
migrate the local schema if needed
reconstruct pending operation O
reconcile with the server before resuming uncertain work
server confirms report and required attachments
commit the acknowledgment locally
UI may now say “Submitted”
The ordering is deliberate. If queue insertion happens only after the network call starts, termination can erase the user’s intent. If the photograph remains only in a transient camera location or memory buffer, the durable queue points to something that no longer exists. If the client retries a timed-out create without an operation ID, uncertainty can become duplicate reports. If it marks the whole report complete when only the structured fields arrived, the server and user disagree about what was submitted.
An atomic local transaction can keep a report, its attachment references, and its pending operation consistent. The remote workflow cannot be one local transaction, so it needs explicit partial states and a repair policy. A resumable upload session may prevent retransmitting large photographs, but its identifier and expiry semantics must themselves survive process death. A final server-side completion step can verify that all required parts exist before the report becomes complete.
Scheduling is an opportunity, not ownership
Mobile operating systems offer mechanisms for deferred or background work, but they retain control over when that work runs and for how long. A senior answer uses the platform scheduler to improve progress, not as the only place where correctness lives.
State the constraints that affect policy: Does the work require any connection, an unmetered connection, external power, or a particular battery condition? Is the task urgent enough to justify more energy and data use? Can the user trigger a foreground retry? What happens when the scheduler delays work for hours? How are expired credentials or upload sessions renewed without losing the report?
Cancellation also needs a product meaning. If the user deletes a pending report, does the app cancel only future attempts, remove local photographs, request cleanup of partial server uploads, or retain an audit record? If the user signs out, private pending data must not quietly become visible to the next account. These decisions connect lifecycle code to security, privacy, storage, and support behavior.
The same restraint applies to connectivity signals. “Online” does not prove that the service is reachable or that a request will finish. Use connectivity changes as a hint to retry; let request outcomes, timeouts, and reconciliation determine state.
Reconciliation decides whether retries are safe
A timeout leaves the client with incomplete knowledge: the server may have accepted operation O even though the acknowledgment never arrived. The next attempt should first ask or submit using the same stable identity. The server can then return the existing result rather than create another report.
Idempotency solves duplicate application of one operation; it does not solve every conflict. If two devices edit the same report, the client also needs a base version and the product needs a stale-write policy. Silently choosing the last arrival may be adequate for a disposable preference. It is harder to defend when reports contain authored evidence. The system might reject stale submission, merge fields that do not overlap, or preserve both versions for a person to resolve. Whichever policy you choose, keep the user’s material recoverable and make the conflict visible.
Schema evolution belongs in this story too. A pending report can outlive an app release, and an old app can outlive several server releases. Local migrations must preserve queued intent and file references. Server APIs must tolerate a measured population of older clients through a compatibility window. A kill switch can stop a broken path, but it cannot rewrite an already installed binary or repair an irreversible local migration. Mobile rollback is therefore a design constraint, not a closing release detail.
What the familiar rounds reveal
Mobile loops often use ordinary round names, but the inconvenient order of events carries more weight.
In a coding round, expect collection transforms, presentation-state logic, pagination, local search, cancellation, cache behavior, or asynchronous results that return after the screen has changed. Model the states and identities before choosing an abstraction. A search implementation should prevent an old response from replacing a newer query, preserve useful cached results when a refresh fails, and remain testable without a live view or network.
In practical coding, the repository and platform idioms are part of the problem. You may repair a lifecycle bug, add persistence to a form, move side effects out of rendering code, or add a denied-permission state. Prefer the narrowest boundary that makes the behavior inspectable. Tests around process recreation, stale results, partial local writes, and retry are more persuasive than an architectural rewrite completed for display.
In mobile system design, start with the user promise, then place durable local state, server state, work in flight, and visible state. Offline editing, media upload, messaging, authentication, notifications, location features, and cross-platform migrations all expose different policies. A server diagram with a thin phone at its edge has omitted the distinctive system.
In a project deep dive, prepare one story about product or architecture and one about quality in production. Strong material includes a sync failure, crash reduction, startup or rendering investigation, local-data migration, modularization, cross-platform decision, release incident, or permission redesign. Explain the device and OS population, the old-client window, the QA matrix, the rollout, support evidence, and the measurement that changed a decision. Do not sand away the release train and migration work; that is often where ownership becomes visible.
In behavioral and senior screens, quality disagreements need a concrete user consequence. If product wants to accept a known risk of lost reports, describe the affected population, narrower release, preservation mechanism, support path, and escalation threshold. If design wants a permission at first launch, ask what value the user has seen, what least privilege permits, and whether denial leaves a useful product. If iOS and Android differ, separate the product guarantee from platform convention instead of forcing identical implementation or allowing accidental divergence.
Refresh the foundations through consequences
Framework recall is least useful when it floats free of behavior. Refresh the foundations by asking what each lets you predict:
- Lifecycle: what remains after navigation, backgrounding, suspension, process death, restart, and upgrade; what work must be durable first.
- Storage: which data belongs in memory, a database, secure credential storage, app-controlled files, or an evictable cache; how encryption, retention, account changes, low storage, and migrations alter the choice.
- Networking: how cancellation, timeout, retry, backoff, authentication refresh, pagination, uploads, and connectivity changes affect repeated or late work.
- Synchronization: which state is local or shared, how operations are identified, how versions and conflicts work, and which pending or failed states the user can recover.
- Performance and resources: where cold and warm startup, main-thread work, rendering, memory pressure, image handling, network use, thermal limits, and battery cost become visible to a real user.
- Privacy and permissions: why the value, timing, scope, retention, and denied or revoked state matter as much as the prompt itself.
- Architecture: how navigation, presentation state, domain decisions, data sources, dependencies, and modules create test seams without pretending the platforms have no important differences.
For performance, make the population and action explicit. “Startup improved” is incomplete without cold or warm conditions, device class, percentile, app version, and the point at which the user can do useful work. Profile the critical path before prescribing lazy initialization or caching, then protect the gain with a release guardrail. The same discipline applies to frame rendering, memory, battery-sensitive work, and network consumption.
Observe the promise, not only the process
Crash-free sessions cannot tell you that a report remained pending for three days. For the field-report flow, useful operational signals include age and outcome of pending operations, attachment retry and expiry, duplicate suppression, conflict rate, authentication failure, migration failure, and the time from local Submit to server completion. Segment enough to expose app version, OS version, device capability, and network conditions without collecting report contents or other unnecessary private data.
Support needs a comprehensible state too. An operation ID, timestamps, app version, and non-sensitive failure category can help distinguish delayed work from missing work. “Check the crash dashboard” is not a recovery procedure.
Release the change through a bounded cohort when risk warrants it. Decide in advance which signal pauses expansion, activates a kill switch, or requires a forward fix. Keep backend contracts compatible with clients still in the wild, and test migration from versions that real users still run—not only from the immediately previous build.
Failure patterns to catch in your own answers
Several polished answers evade the mobile problem:
- “The server is the source of truth” says nothing about useful work performed while the server is absent. Separate local draft, pending operation, server record, and displayed state.
- “A background worker uploads it” delegates correctness to scheduling the app does not control. Persist the intent and make delayed work visible.
- “Retry with backoff” can duplicate an uncertain side effect. Give the operation a stable identity and reconcile before repeating it.
- “We can roll back” ignores store review, staged delivery, users who do not update, local migrations, and changed server data. Design compatibility, flags, and forward repair before release.
- “We track crashes” misses failed flows, slow startup, battery cost, sync age, and support harm. Instrument the promise.
- “Ask for permission and handle denial” treats consent as an API branch. Establish value, request least privilege at a relevant moment, and keep the denied or revoked state useful.
- Platform trivia without a user consequence demonstrates recall, not senior judgment. Tie each mechanism to lifecycle, state, privacy, performance, release, or recovery.
Practice with interruptions that change the answer
Use a few bounded rehearsals rather than memorizing a mobile speech:
- Design the field-report flow above. Then terminate the process after each local and remote step. Mark what survives, what may repeat, and what the UI is allowed to say.
- Implement a cached search whose old network response arrives after a new query. Test cancellation, stale-response suppression, empty state, offline state, failure, and screen recreation.
- Add a second device to an offline editing design. Choose a conflict policy that preserves authored work, then add an old client that does not understand the newest server field.
- Investigate slow startup on lower-capability devices. Define usability, segment the measure, inspect the critical path, constrain one change, and choose a regression guardrail.
- Review a location or notification feature. Decide when to ask, what the least privilege is, what happens after denial or revocation, and which data should never be retained.
- Rework one project story to include process death, schema migration, version skew, rollout, support, and the evidence that users were better off.
After each attempt, name the boundary you failed to make concrete: user promise, durable local state, remote authority, operation identity, conflict policy, lifecycle, resource cost, privacy, compatibility, observability, or recovery. That missing boundary is the next practice assignment.
A compact mobile answer frame
When a prompt sprawls, make these lines specific:
User promise and what each visible status means:
Durable local state and server authority:
Interruption or resource constraint most likely to break the promise:
Operation identity, retry, and reconciliation policy:
Conflict, permission, and user-recovery behavior:
Old-client, migration, rollout, and repair plan:
Flow, performance, privacy, and support evidence:
You are ready when you can reason through backgrounding, process death, reconnect, retry, conflict, upgrade, permission denial, and resource pressure without turning them into a list of APIs. The phone will eventually disappear between two steps. A senior mobile design makes that ordinary: the user’s work survives, repeated effects are controlled, and the interface never claims more than the system knows.
Related links
Continue reading
Full table of contents