Mobile — Mobile App Architecture
Domain-Driven Design for Mobile Product Teams
Direct answer
Domain-driven design for mobile teams is worth adopting selectively: take the strategic tools — ubiquitous language and bounded contexts mapped to feature modules — and a thin slice of the tactical ones, like value objects and domain events where invariants genuinely matter. Skip the heavyweight patterns built for server-side systems. The result is a mobile codebase whose modules mirror how the business actually talks and decides, which is what makes it cheap to change.
DDD has a reputation as enterprise ceremony, so mobile teams dismiss it — then spend years paying for models that mean different things on every screen. The useful core of DDD fits mobile development surprisingly well. This is the subset I bring to product teams and the parts I deliberately leave out.
Key facts, with sources
- React Native's New Architecture became the default in 0.76, the legacy bridge was retired in 0.82, and Hermes V1 shipped as the default JavaScript engine in 0.84. (TO THE NEW Blog)
- Microsoft retired Visual Studio App Center and CodePush on March 31, 2025, forcing every team that depended on it to migrate their over-the-air update architecture. (microsoft/react-native-code-push GitHub issue)
- In the State of React Native 2024 survey, Redux drew the most negative feedback at around 18% dissatisfaction, while React's built-in state management (31% positive) and Zustand (21% positive) were the best regarded. (InfoQ)
- Over 80% of State of React Native 2024 respondents work in teams of up to five developers, meaning most mobile architectures must be maintainable by very small teams. (SSOJet (State of React Native 2024 highlights))
- Published production examples report Shopify at 86% unified code across its apps and Instagram sharing 85 to 99% of code between iOS and Android. (CatDoes)
The mobile-shaped version of the problem
Mobile codebases accumulate a specific kind of rot: the same business concept modeled three ways. An "order" means one thing on the tracking screen, another in checkout, and a third in the API layer, with translation code and subtle bugs at every seam. Screens end up owning business rules because there was no agreed model to put them in, so rules drift apart as screens evolve independently.
DDD's core claim is that this is a language problem before it is a code problem. When engineers, designers, and product managers use the same words with the same meanings — and the code uses those words too — the translation layers and their bugs largely disappear. That claim holds on mobile just as it does on the backend, and mobile teams are rarely the ones at the table when the language gets defined. They should be.
Ubiquitous language in practice
Ubiquitous language sounds abstract until you enforce it concretely: the words product uses in specs are the words in type names, store names, analytics events, and screen files. If the business says "quote" and the code says "estimate," pick one, rename, and move on. I keep a short glossary in the repo — one line per term — and treat naming drift in code review as a real defect, not pedantry.
The payoff is compounding. Onboarding accelerates because the codebase reads like the product conversations. Cross-functional debugging gets faster because a bug report written in product language points directly at the module with that name. And requirements ambiguity surfaces earlier: when a product manager uses a term the glossary does not contain, that is a modeling conversation you get to have before the code is written instead of after.
Bounded contexts map to feature modules
A bounded context is a boundary inside which a model is consistent — and it legitimizes something mobile teams feel guilty about: the same real-world thing can be modeled differently in different features, on purpose. A "customer" in the loyalty feature carries points and tiers; a "customer" in checkout is a payment method and address. Forcing one god-model to serve both produces the bloated types with thirty optional fields that plague mobile codebases.
Practically, bounded contexts become your feature module boundaries: each feature owns its model, and cross-feature communication happens through small translated interfaces rather than shared types. This gives folder structure a principled basis — modules are drawn where the language changes meaning, not where a technical layer happens to end. When two features keep needing each other's internals, that is evidence the context boundary is drawn wrong, which is a design conversation, not a lint exception.
Tactical patterns worth keeping — and skipping
From the tactical toolbox I keep three things on mobile. Value objects: small immutable types like money, quantity, or date range that carry their own validation, eliminating the primitive-obsession bugs where a raw number crosses six functions before anyone checks it. Domain events as names for meaningful state changes — order submitted, trip completed — which line up beautifully with analytics and realtime updates. And plain-TypeScript domain services for rules too big for one type.
I skip aggregates with strict consistency boundaries, repository abstractions over every fetch, and factory hierarchies — those patterns earn their weight guarding transactional writes in server systems. A mobile client is mostly an edge cache with a UI; its writes go through an API that enforces the real invariants. Importing server-side ceremony into the client adds indirection with no invariant left to protect.
Aligning with the backend without waiting for it
The ideal is shared context boundaries across backend and mobile, with API contracts expressed in the ubiquitous language. Reality is usually messier: the backend has its own history, and its models may be exactly the tangle you are escaping. The anti-corruption layer is DDD's answer, and mobile teams already build one without naming it — the mapping layer where API responses become client types. Make it explicit: translate wire formats into your context's model at the API boundary, and never let backend naming leak past it.
This means mobile does not have to wait for a backend refactor to get a clean model. It also gives you a concrete artifact for cross-team conversations: when the translation layer for one endpoint grows painful, that is measurable evidence for the API design discussion, far more persuasive than aesthetic complaints about naming.
When to hire senior help
Architecture is the cheapest place to buy senior expertise, because decisions about state management, navigation, offline strategy, and update infrastructure made in week one determine costs for years. A short engagement with a senior mobile architect before or during MVP planning routinely prevents the rewrite-at-scale scenario that hits teams around their first major growth phase. If your stack includes React Native + Python + AI, a senior engineer who owns the full product beats coordinating multiple juniors.
Bottom line
Dhairya Senjaliya ships Mobile — Mobile App Architecture projects worldwide — book a scoping call to discuss your specific situation.
Common pitfalls to avoid
- ✕Adopting Redux with sagas and heavy boilerplate for a five-screen MVP when built-in React state or Zustand would cover the actual requirements
- ✕Scattering business logic inside UI components instead of isolating a data layer, making later backend changes or native module swaps expensive
- ✕Building deployment architecture on a hosted OTA service with no exit plan, a risk the March 2025 CodePush shutdown made concrete for thousands of teams
- ✕Assuming permanent connectivity and bolting on caching later, instead of designing offline storage and sync conflict resolution before the data layer hardens
Frequently asked questions
Is domain-driven design overkill for a mobile app?
Full tactical DDD, yes — aggregates and repository hierarchies solve server-side consistency problems a mobile client does not have. The strategic core is not overkill at any size: shared vocabulary between product and code, and feature modules drawn where the business language changes meaning. Those two practices cost little and prevent the god-models and duplicated rules that make mobile codebases expensive.
How does DDD relate to feature-based folder structure in React Native?
DDD supplies the principle that decides where feature boundaries go. A bounded context — a boundary inside which terms have one consistent meaning — becomes a feature module, owning its own model and exposing a small translated interface to other features. Feature folders without that principle tend to be drawn by screen groupings, which drift; language boundaries are more stable.
What is an anti-corruption layer in a mobile app?
It is the explicit mapping boundary where API responses are translated into your app's own domain types, so backend naming, quirks, and legacy structures never leak into feature code. Most apps have an accidental version of this in their API layer. Making it deliberate means a backend field rename or messy endpoint touches one mapping file instead of dozens of screens.
What state management should a new mobile app use?
For most apps, React's built-in state plus a light library like Zustand is enough; in the State of React Native 2024 survey those two drew the most positive sentiment while Redux drew the most negative at about 18% dissatisfaction. Heavier tooling is justified mainly by large teams, complex shared state, or strict audit requirements.
Do we need offline support from day one?
If users operate in the field, in transit, or in markets with unreliable networks, yes, because retrofitting offline-first sync onto an online-only data layer is one of the most expensive refactors in mobile. If the app is unusable without live data anyway, graceful error and retry handling may be sufficient.
What are over-the-air updates and should our app use them?
OTA updates push JavaScript-level fixes directly to users without waiting for app store review, which is valuable for hotfixes. Microsoft's CodePush was retired on March 31, 2025, so current options are EAS Updates, a self-hosted CodePush server, or third-party services, and updates must stay within store policies that prohibit changing an app's core purpose.
Bottom line: Dhairya Senjaliya ships Mobile — Mobile App Architecture projects worldwide. Book a scoping call at https://dhairyasenjaliya.com/#book-call.