Arvension
Arvension Technologies
← Back to Blog

Mobile App Architecture: Lessons From Eight Years

Shipping production mobile apps since 2017. Architectural decisions that held up, ones that didn't, and what I'd do differently if I started over today.

AA

Abhi Asok

Founder & CEO, Arvension Technologies

9 min read

I've been shipping production mobile apps since 2017. That sounds shorter than it is—eight years in mobile dev is like dog years. Everything changed twice.

I want to talk about the architectural decisions I made that held up, the ones I regret, and what I'd do differently now.

The Decisions That Held Up

Treating the network as unreliable. From day one, I assumed the network could disappear at any time. Offline-first architecture. Every screen has fallback data. Every action queues if the network isn't available. This saved me repeatedly. Every mobile app I know that shipped without this ended up retrofitting it at great cost.

Separating business logic from UI. Whether you call it MVVM, Redux, Clean Architecture, doesn't matter. What matters is that business logic isn't baked into your view controllers or React components. It's testable, reusable, independent of UI framework changes. This paid for itself when we migrated from one framework to another. The logic came with us. Only the UI needed rewriting.

Building an abstraction over API communication. Not making REST calls directly from your components. Instead, a service layer that normalizes API responses, handles retries, handles rate limiting, logs errors. This abstraction insulated us from backend changes. When the API changed, we updated the service layer. Everything downstream worked unchanged.

Strong typing where it mattered. TypeScript on the frontend, protocol buffers or generated types on the backend. You catch whole categories of bugs at compile time. In mobile, where debugging is harder than web, this was huge.

Investing in testing infrastructure early. Snapshot tests, unit tests, integration tests. I invested in test infrastructure in 2017 and it felt like overkill. By 2020, when we were shipping features to millions of users, it was the only reason we could refactor without terror.

These five things: offline-first, separated business logic, API abstraction, strong typing, and testing. They held up through every framework change, every scale problem, every pivot.

The Decisions I Regret

Using MobX for state management. I chose MobX in early React Native projects. It felt elegant at the time. It was actually hard to reason about. State mutations were implicit. Debugging was a nightmare. By 2019, I moved to Redux. Lost a lot of productivity migrating.

Building custom navigation. React Navigation didn't exist early. I built custom navigation in one project. It worked okay at first. As the app got complex, custom navigation became a liability. Switching to a real navigation library was one of the best decisions I made. Never build what exists.

Not investing in design tokens early enough. I hard-coded colors, spacing, font sizes in components. When design changed, it was chaos. I finally invested in a design system, centralized tokens, and suddenly design changes were easy. Should've done it in year one.

Delaying analytics infrastructure. I didn't instrument apps heavily early on. When we wanted to understand user behavior, we had huge gaps. Had to retroactively add analytics. If I could do it over, analytics goes in day one. Not intrusive. Not creepy. Just: track which screens people visit, which actions they take, where they get stuck.

Optimizing prematurely. I spent months in early apps optimizing performance that didn't matter. Frame rate on a list that never had more than 50 items. Memory optimization on animation loops. This distracted from real problems: shipping features, fixing actual bugs. I should've measured first, optimized second.

What I'd Do Differently

If I were starting a mobile project from scratch today:

I'd use a meta-framework. Expo, Tamagui, or something equivalent. The friction of managing native builds is too high. Let someone else own that.

I'd architect for monorepo from day one. Web, mobile, backend API specs—all in one repo. Shared types, shared business logic, shared test infrastructure. The coordination overhead is worth the duplication you eliminate.

I'd invest in error boundaries and error handling early. Not generic error handling. Specific error boundaries that catch different failure modes and handle them intelligently. Timeout. No network. Invalid data. Different UX for each.

I'd be ruthless about dependency selection. Less is more. A few high-quality dependencies beat many okay ones. Every dependency is a liability.

I'd design for feature flags from the beginning. Not as an afterthought. Every feature hidden behind a flag. This changes everything about how you deploy: you can ship broken code and toggle it off. That removes so much risk.

I'd separate MVP scope from "things we'll add later." I've watched so many mobile projects fail because they tried to ship too much too fast. Build the core experience first. Make it work perfectly. Then add features. The projects that followed this were faster to launch and had better quality.

The Landscape in 2025

The mobile architecture landscape is more mature now. You have good defaults:

  • Use Expo if you need to ship fast
  • Use TypeScript for type safety
  • Use a real state manager (Redux, Zustand, Jotai)
  • Use a real navigation library
  • Test early and often

The interesting architectural questions now aren't about framework choices. They're about:

  • How do you coordinate features across mobile and web?
  • How do you handle AI features in mobile apps?
  • How do you manage offline-first state with real-time sync?
  • How do you handle complex animations and interactions?

These are the problems I'm thinking about in 2025. The framework choices are mostly settled.

What Stuck With Me

The core lesson: architecture is about optionality. Good architecture makes future changes possible. It makes refactoring possible. It makes testing possible.

The worst architecture I've shipped was the one that felt fine at the time but made every change after that a nightmare. The best architecture was the one that felt like overkill initially but made scaling possible.

If I were mentoring someone starting mobile dev today, I'd say: don't optimize for immediate speed. Optimize for the ability to change your mind later. Build with enough structure that refactoring is possible. Not rigid. Just structured.

That's held true for eight years. I think it'll hold true for eight more.

Related Articles