Mobile Engineering
Building the software that runs on a phone the OS can suspend, kill, or starve of memory at any moment - iOS and Android architecture, state that survives what the system does to it, and the discipline of designing for a device you do not control.
Assumes you know: One general-purpose language you can write without a tutorial open, Basic object-oriented and asynchronous programming concepts, Comfort reading a stack trace and using a debugger
Overview
What this area actually covers
Mobile engineering is the work of building software that runs inside an operating system whose primary loyalty is to the device's battery and memory, not to your app. Concretely, it covers the platform-specific frameworks for building a UI (UIKit and SwiftUI on iOS, the View system and Compose on Android), the concurrency models each platform uses for anything that cannot happen instantly (structured concurrency in Swift, coroutines in Kotlin), the lifecycle contracts that govern when your code runs and when it is paused or killed without warning, and the operational realities of shipping to a device you do not own and cannot inspect after the fact - a variable network, a battery the user is protecting, storage the OS will reclaim from you if you are careless with it.
It is easiest to place by naming its two neighbours. Below it sits general application programming: writing correct Swift or Kotlin, choosing data structures, calling an API and parsing a response - skills that transfer from any other kind of software and that a mobile interview mostly assumes rather than tests. Above it sits distributed systems and backend design, which mobile engineering touches constantly (every app talks to a server) but does not own; a mobile engineer designs the client's behaviour when a server is slow or unreachable, not the server's own resilience. Mobile engineering is the layer in between: given a UI toolkit and a network, build something that behaves correctly when the OS suspends it mid-task, when memory runs low, when the network disappears for a train tunnel's worth of time, and when the user rotates the device or backgrounds the app at the exact moment a request was in flight.
What gets wrongly bundled into it. General software design patterns - MVC, MVVM, dependency injection - are not mobile-specific and a candidate who can only discuss them in the abstract, without connecting them to an actual lifecycle constraint a phone imposes, is demonstrating general architecture knowledge rather than mobile depth. Backend API design is a separate discipline that a mobile engineer consumes rather than owns, though a genuinely senior mobile engineer can usually hold a informed opinion about what the API should look like given what the client needs to do with the response. And UI visual design - typography, spacing, colour, the platform's human-interface guidelines - is a real and valuable skill but is design work, examined separately from the engineering skill of making that design actually behave correctly once state, memory and the network get involved.
The single idea that runs through nearly every hard question in this area is that a mobile app does not control its own lifetime. A backend service, badly written, mostly just runs slowly or crashes under its own logic's failure. A mobile app, well written, still gets suspended mid-task, killed without a callback, and asked to resume as though nothing happened - and the entire discipline of state restoration, memory management, and offline resilience exists because the OS reserves the right to do all three to you at any moment, for reasons that have nothing to do with your code being wrong.
The two areas underneath
This section is divided by platform rather than by topic, because the concerns that separate a strong from a weak answer are largely platform-specific in their exact mechanism even where the underlying problem - state loss, memory pressure - is the same on both sides. Read the one matching the role in front of you; the vocabulary differs enough between platforms that studying only one will not transfer directly to an interview on the other, even though the reasoning behind both usually will.
iOS Architecture covers SwiftUI's declarative state model and its specific pitfalls (view identity, observation granularity, retain cycles through closures and delegates), UIKit's imperative view-controller lifecycle for the codebases that still run on it, Swift's memory model under Automatic Reference Counting, and the practical question of how to modularise a large iOS codebase into Swift packages as it grows past what one team can hold in their heads. It exists as its own subsection because Apple's platform makes specific, opinionated choices - value-type views, compiler-enforced main-thread isolation via @MainActor, ARC instead of a tracing garbage collector - that produce a distinct set of bugs and a distinct interview vocabulary from Android's equivalent concerns.
Android Architecture covers Kotlin's coroutines and structured concurrency, Compose's recomposition model and its own distinct performance pitfalls, and the background-work landscape Android exposes through WorkManager, foreground services, and (rarely, correctly) AlarmManager, plus the two-part guarantee of ViewModel surviving configuration changes while SavedStateHandle separately survives process death. It exists as its own subsection because Android's app model is fundamentally more willing to kill your process than iOS's is, and a correspondingly larger share of the discipline here is about designing for that willingness rather than around it - Doze mode, app standby buckets, and the process-death-versus-configuration-change distinction are Android-specific vocabulary with no precise iOS equivalent.
| Subsection | What it is for |
|---|---|
| iOS Architecture | SwiftUI's state model, ARC and memory, and structuring a large Swift codebase |
| Android Architecture | Coroutines, Compose recomposition, and surviving what the OS does to your process |
Where it sits in a real system
A mobile app is one participant in a system it does not fully see. It talks to a backend over a network it does not control, it runs on hardware whose model, OS version and available memory vary by orders of magnitude across the install base, and it is subject to an operating system that actively manages its lifetime rather than merely hosting it. Understanding where mobile work sits means tracing what happens to a single user action from tap to result, because every step along that path is a place the app can be interrupted.
flowchart TD
A[User taps a button] --> B[UI layer captures intent]
B --> C[ViewModel or state<br/>object updates]
C --> D[Repository decides:<br/>local cache or network]
D --> E[Network request,<br/>with a timeout]
E --> F[Local store updated<br/>on response]
F --> G[UI observes the store<br/>and redraws]The step worth pausing on is the arrow from D to E. Everything after it can be interrupted by something the app has no say over: the OS can suspend the process between the request being sent and the response arriving, the network can vanish mid-transfer, and the user can navigate away from the screen that initiated the request before it completes. A well-designed mobile architecture treats that arrow as the boundary where things go wrong, and puts the recovery logic - what happens if this never completes, what the UI shows meanwhile, whether the request is safe to retry - at exactly that boundary rather than scattered through the UI layer that triggered it.
The layer diagram understates one thing worth stating directly: the repository box is doing two structurally different jobs that interviewers probe separately. It decides whether to serve from a local cache or go to the network (a caching and freshness decision), and separately it decides what the local store's relationship to the network's eventual answer is once that answer does arrive (a sync and conflict-resolution decision). An offline-first app makes the local store the actual source of truth the UI reads from at all times, with the network purely updating that store asynchronously in the background - which is a different and stronger design than a cache that merely stands in front of the network and gets bypassed the moment connectivity returns.
The operating system sits above this entire diagram as a layer most system-design thinking forgets to draw, because a backend service does not have an equivalent of it: something that can pause every box in the diagram simultaneously, mid-flight, with no notice, to protect a resource the app does not own. That is not a metaphor - it is the literal behaviour of both platforms' memory managers, and it is why "what happens if the process is killed right here" is a legitimate follow-up to almost any design a candidate draws in this space, in a way it rarely is for a server-side design.
Who does this work
The core builders are iOS engineers and Android engineers, most of whom specialise in one platform even at senior levels, because the frameworks, the tooling, and the specific failure modes diverge enough that deep fluency in both simultaneously is uncommon outside platform teams at large mobile-first companies. A typical day is a mix of feature work inside an existing screen's architecture, debugging a crash report that reproduces on one device model and not another, and reviewing whether a change to shared state could reintroduce a lifecycle bug the codebase has already been burned by once.
Mobile platform engineers sit a layer up: they own the shared infrastructure other feature teams build on - the networking layer, the dependency-injection setup, the CI pipeline that builds and signs the app, the crash-reporting integration - and are judged less on any one feature and more on how rarely other engineers have to think about the plumbing at all. Cross-platform engineers, working in React Native, Flutter, or Kotlin Multiplatform, take on a distinct trade: less platform-specific code to write, in exchange for owning the seams where the abstraction does not quite cover a native capability and a bridge has to be written by hand.
Mobile tech leads specify the architecture a team of feature engineers builds against - the state-management pattern, the module boundaries, the offline strategy - and in most organisations senior individual engineers do a meaningful share of this work without the title. The distinction that shows up fastest in an interview is the same one backend engineering carries: between someone who has shipped features inside an app someone else architected, and someone who has watched their own architectural choices get tested by two years of feature growth and a few production incidents caused by a lifecycle edge case nobody anticipated.
Demand, adoption and how that is changing
Demand for mobile engineers is high and structurally durable, because a mobile app remains, for most consumer and many enterprise products, the primary or only interface a user has to the business - there is no equivalent of "we'll just use the desktop site" for a large and growing share of use cases, particularly outside markets where desktop ownership is the default. That baseline demand is not tied to any single technology cycle the way, for instance, demand for a specific frontend framework can be, because the underlying platforms (iOS, Android) are stable, long-lived, and not going anywhere.
What is genuinely shifting is the balance between fully native development and cross-platform frameworks. React Native and Flutter have matured enough that a meaningful share of new consumer apps start cross-platform by default, particularly at companies optimising for one team shipping to two platforms rather than two teams shipping to one each - a real organisational cost saving that shows up directly in hiring patterns. That has not eliminated native demand; it has concentrated native hiring more heavily at products where platform-specific capability, performance headroom, or the newest OS features genuinely matter enough to justify the extra team, and at the platform-engineering layer inside larger mobile organisations regardless of what the feature teams above them are using.
The declarative UI shift - SwiftUI on iOS since 2019, Compose on Android since 2021 - has also changed what "mobile experience" means as a hiring signal. A candidate whose experience is entirely in the older imperative toolkits (UIKit, the Android View system) is not obsolete, because a large share of production code at established companies is still built on them and will be for years, but is increasingly expected to be conversant in the declarative model as well, because that is where new development is concentrated and where the newer interview material increasingly sits. Kotlin Multiplatform's growth is the most recent adoption signal worth naming honestly: it is real and growing, particularly for sharing business logic between iOS and Android without giving up a fully native UI on either side, but it remains a minority approach relative to either fully native or fully cross-platform development, and treating it as already dominant would overstate where the industry actually is.
What makes it hard
The defining difficulty is that the operating system, not your own code, decides how long your process lives, and a huge share of mobile engineering skill is designing for that fact rather than around it. A backend engineer who writes a bug can usually reproduce it by calling the buggy code again. A mobile engineer's hardest bugs often only manifest when the OS suspends the process at one specific point in an operation, or kills it under memory pressure that a developer's own test device, usually a recent, well-resourced phone, never actually experiences - which is exactly why "test process death, not just rotation" and "test on a low-memory device, not your own" are recurring pieces of advice that experienced mobile engineers repeat to juniors and that juniors reliably ignore until they have been burned once.
The second genuine difficulty is that state management on both platforms' newer declarative frameworks looks deceptively simple in a tutorial and becomes genuinely subtle at scale. SwiftUI's and Compose's whole promise is that you describe state and the framework figures out what to redraw, and that promise holds cleanly for a small screen with a handful of properties. It gets substantially harder once a screen's state model grows large enough that the granularity of observation - which specific property change triggers which specific redraw - starts to matter for actual scroll performance, and diagnosing that requires understanding a compiler-level mechanism (stability inference, in Compose's case) that no amount of reading the UI framework's basic tutorial prepares you for.
The third difficulty, less discussed but real, is that mobile engineering has an unusually wide range of hardware and OS-version fragmentation to reason about simultaneously, particularly on Android. A design that is correct and fast on this year's flagship device can be a crash risk on a three-year-old budget device with a quarter of the RAM, and the correct engineering response - test on low-end hardware, decode images to display size rather than native resolution, understand what each memory-pressure signal actually asks you to release - is a discipline that has to be learned deliberately, because it will never show up as a bug on the hardware most engineers actually develop on.
Why study it
The most durable reason is that phones are where most people's actual daily interaction with software happens, so the discipline of making software behave correctly under real constraints - a real network, a real battery, a real amount of memory - has an unusually direct line to whether a product actually works for the people using it. That is a genuinely different kind of engineering satisfaction from backend work, where correctness is often invisible to the end user by design; a mobile engineer's bugs and fixes are visible on the actual screen the user is looking at.
It is also one of the better places to build a concrete, non-theoretical understanding of concurrency and lifecycle management, because the platforms force the issue in ways a simple backend service does not - you cannot ship an app that ignores what happens when the process is suspended mid-task, in the way you can sometimes ship a backend service that has never actually been tested against a mid-transaction crash. Learning structured concurrency through Swift's actor model or Kotlin's coroutine scopes, because the platform requires it rather than because a textbook recommends it, tends to produce an understanding that transfers.
The honest case against it: if what motivates you is the deepest layers of a distributed system - consensus, replication, the guts of a database - mobile engineering will feel like it spends most of its difficulty budget on a single client's lifecycle rather than on the problems you find interesting, and you would be better served studying backend or distributed systems directly. And if your interest is specifically in machine learning or data infrastructure, mobile is, at best, the delivery mechanism for that work rather than the work itself; it is worth knowing enough to ship an ML feature to a phone competently, but it is not the fastest route to depth in the modelling itself.
Your first hour
Build one screen, on whichever platform matches the role you are targeting, that fetches a small list from a real network endpoint and displays it - then break it deliberately in the three ways that generate most of the interview material in this area. First, rotate the device (or trigger the equivalent configuration change) while the fetch is in flight, and confirm the screen does not lose its data or fire the request twice. Second, force the process to die - Android Studio's kill-activity option, or backgrounding and waiting on iOS - and confirm what actually survives versus what silently resets, because this is the test most tutorials skip and most interview follow-ups target directly. Third, turn off the network entirely mid-session and watch what the screen does: a real answer to "what happens offline" requires having actually seen it happen once, not assumed it.
The artefact worth keeping from that hour is not the code itself but four written sentences: what survives a configuration change, what survives process death, what the screen shows with no network, and what happens if the same request fires twice. Those four sentences are the compressed form of most of what a mobile architecture interview is actually checking for, and having genuinely tested them once, rather than reasoned about them abstractly, is the difference the interviewer is listening for.
What this is not
It is not general software engineering with a different UI on top. The frameworks are genuinely platform-specific, and the failure modes - lifecycle-driven state loss, memory pressure under an OS that actively reclaims resources, offline resilience against a network the user is carrying in their pocket rather than sitting in a data centre - do not have a close analogue in most backend or web frontend work, which is why fluency in one does not transfer automatically to the other despite both being "just" building software with a UI.
It is not the same discipline as UI or UX design, even though the two collaborate constantly and a mobile engineer needs enough taste to notice when a design will not survive contact with a real device. Choosing a colour palette or an interaction pattern is design work; making that interaction pattern actually behave correctly when the OS interrupts it mid-gesture is engineering work, and the two are examined separately for good reason.
It is not a solved argument between native and cross-platform, and treating either side as obviously correct is itself the tell interviewers watch for. Both approaches have shipped excellent and terrible apps, the right choice depends on the specific product's need for platform-specific capability versus the organisation's need to move one team across two platforms, and the strongest answer in an interview names that trade explicitly rather than asserting a general preference.
Nearly every hard question in this area reduces to the same fact stated differently: the operating system will suspend, kill, or starve your app of memory whenever it decides to, and the entire discipline is designing for that with confidence rather than discovering it in production.
Where to go next
Now practise it
8 interview questions in Mobile Engineering, each with the rubric the interviewer is scoring against.
- An Android app queues actions while offline. After the process is killed and restarted, some actions sync twice and the user sees duplicate orders. How do you design the fix?
- A Compose screen with a long list is janky while scrolling - walk through how you'd find and fix the recomposition problem causing it.
- You're asked to break up a five-year-old iOS app that has become one enormous Xcode target - how would you approach modularising it, and what does it cost you?
- How do retain cycles happen in Swift closures and delegates, and how would you find one in an app that is slowly leaking memory?