Software Engineering · Chapter 13 of 31
Mobile engineering, and the constraints that shape it
Why mobile is not frontend with a different renderer: you cannot hot-fix, the platform can reject you, and the device is hostile.
Mobile engineering looks like frontend from the outside and differs in four constraints that change every decision. Candidates who articulate those constraints do well; candidates who treat it as web development with a different view layer do not.
The four constraints
- 1 · You cannot fix it immediately. A web bug is fixed by a deploy. A mobile bug requires a build, a store review, and then users choosing to update. Even with a fast review, a meaningful share of your users will be on the broken version for weeks. This single fact is why feature flags and remote configuration are not optional on mobile — they are the only mechanism you have for changing behaviour after release.
- 2 · You do not control distribution. A platform can reject your release for reasons that are not about correctness, and you have limited recourse. Release planning has to include review time and the possibility of rejection.
- 3 · The device is hostile. Battery, thermal throttling, memory pressure that gets your process killed without warning, an operating system that suspends you in the background, and a network that disappears in a lift. Every one of these is a normal operating condition rather than an error case.
- 4 · Multiple versions run forever. Your API must serve the version you shipped two years ago, because some users never update and some cannot. Mobile backends have the hardest backward-compatibility requirement in the industry and people who have only done web frequently underestimate it.
The consequence that follows from all four
You must be able to change behaviour without shipping a build.
Feature flags and remote configuration for behaviour. A server-driven approach for anything that changes often — if the layout of a promotional screen is defined by a server response rather than by the binary, you can change it without a release.
A kill switch on every risky feature, so a bad rollout is a configuration change rather than an emergency submission.
And a forced-upgrade mechanism for the case where you genuinely cannot support an old version any more. It is unpleasant, users dislike it, and having it is far better than needing it and not having it.
Being able to state this chain — from ‘you cannot hot-fix’ to ‘therefore remote config is architecture, not tooling’ — is the clearest signal of mobile experience in an interview.
Native, cross-platform, or web
| Approach | Genuinely good at | Genuinely bad at |
|---|---|---|
| Native (platform language and toolkit) | Performance, immediate access to new OS features, platform-idiomatic feel, the hardest graphics and camera work | Two codebases, two teams, two release trains, and feature drift between them |
| Cross-platform, own renderer | One codebase with genuinely consistent UI, good performance, strong tooling | Larger binaries, and it looks the same everywhere — which is a virtue or a flaw depending on the product |
| Cross-platform, native widgets | Reuse of web skills and ecosystem, platform-native look | A bridge to reason about, and platform-specific work still leaks in |
| Progressive web app | No store, instant updates, one codebase | Restricted platform capabilities, weaker background execution, and no store presence — which matters commercially more than technically |
The honest position: the choice is usually about team and product economics rather than technology. Two native codebases needs two teams; if you have one team of five, cross-platform is likely right regardless of the performance argument. If your product's value is a camera pipeline or a game, native is likely right regardless of the cost argument. The candidates who answer with a technology preference are answering the wrong question.
What actually goes wrong in production
- Memory pressure and process death. The operating system kills backgrounded applications freely. Your application must be able to restore its state from nothing — and the bug is that it looks fine in development, where the process is never killed, and produces mysterious 'lost my work' reports in the field.
- Offline and flaky networks. Not a special case. Design for it: a local store as the source of truth for the UI, a sync layer, and an explicit conflict policy. Retrofitting offline support is close to a rewrite, which is why it should be decided at the start.
- Background execution limits. Both platforms aggressively restrict what runs in the background, and the rules change between OS versions. Anything that must happen reliably belongs on the server, triggered by a push, rather than in a background task you hope will run.
- Battery and thermal. Frequent wake-ups, continuous location, and unbatched network requests drain batteries and get applications uninstalled. Batching and deferring is a design decision, not an optimisation.
- Fragmentation. Screen sizes, OS versions, manufacturer modifications, and wildly varying hardware. Test on a genuinely cheap device, because it is what a large share of the world uses and it will find problems no flagship reveals.
Release engineering, which is most of the discipline
Because you cannot hot-fix, the release process carries far more weight than on the web:
- Staged rollout, always. Both stores support releasing to a percentage. Watch crash-free rate and the key business metric before proceeding, and halt rather than hope.
- Crash-free sessions is the headline health metric, and the number to watch is the change after a release rather than the absolute value.
- Keep the release train regular. A predictable cadence is better than shipping when ready, because it decouples feature completion from release and stops one late feature holding everything.
- Version your API from the first release. Deciding this later, once three versions are in the wild, is painful.
- And instrument what you cannot see. You have no access to the device; crash reporting, structured analytics and remote logging are how you find out anything at all. A mobile bug with no telemetry is frequently unreproducible and therefore unfixable.
Check yourself