DEV Community

Bhupesh Chandra Joshi
Bhupesh Chandra Joshi

Posted on

How Instagram, WhatsApp, Uber & Netflix Would Be Built Today Using Expo Router

Modern large-scale mobile apps demand maintainable architecture, scalable navigation, robust state management, and production-grade performance. Expo Router makes this achievable in React Native with file-based routing inspired by Next.js.

1. How Modern Large-Scale Mobile Apps Are Structured

Today's apps like Instagram, WhatsApp, Uber, and Netflix follow modular, feature-driven architectures. Core principles include:

  • Separation of concerns: UI, business logic, data, and navigation are isolated.
  • Scalability: Easy onboarding for new developers and adding features without breaking existing code.
  • Performance: Lazy loading, code splitting, and optimized rendering.
  • Cross-platform consistency: Shared code for iOS, Android, and often web.

Expo Router excels here with its file-system routing, nested layouts, and built-in support for deep linking, protected routes, and async bundles.

2. Why Architecture Matters in React Native Applications

Poor architecture leads to "spaghetti code," slow performance, difficult debugging, and scaling bottlenecks. A solid structure:

  • Reduces bugs and improves maintainability.
  • Enables parallel development by teams.
  • Supports offline capabilities, real-time updates, and complex navigation.
  • Optimizes bundle size and startup time for production apps serving millions.

In large apps, feature-based separation trumps simple type-based folders (e.g., all components in one place).

3-4. Folder Architecture Using Expo Router + Feature-Based Separation

A scalable structure often looks like this (inspired by community best practices):

src/
├── app/                      # Expo Router routes (file-based)
│   ├── (auth)/               # Route groups (no URL segment)
│   │   ├── login.tsx
│   │   └── _layout.tsx
│   ├── (tabs)/               # Bottom tabs
│   │   ├── home/
│   │   ├── explore/
│   │   └── profile/
│   ├── feed/
│   ├── chat/[id].tsx         # Dynamic routes
│   └── _layout.tsx           # Root layout
├── features/                 # Feature-based modules
│   ├── feed/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── api.ts
│   │   └── store.ts
│   ├── chat/
│   ├── ride/                 # For Uber-like
│   └── profile/
├── components/               # Shared UI (design system)
├── lib/                      # Utils, API client, config
├── hooks/                    # Global custom hooks
├── store/                    # State management
├── services/                 # API, realtime, storage
├── types/
└── utils/
Enter fullscreen mode Exit fullscreen mode

Benefits: Routes reflect user flows. Features are self-contained (screens + logic together), making them easy to move, test, or remove.

5. Navigation Architecture for Scalable Apps

Expo Router uses file-based routing with powerful layouts:

  • _layout.tsx files define Stack, Tabs, or Drawer navigators.
  • Route groups (group) for logical grouping without URL impact.
  • Nested routing for complex flows (e.g., tabs inside a stack).
  • Deep linking and universal links out of the box.
  • Shared layouts for consistent headers, sidebars, or tab bars.

Example for Instagram-like tabs + modals:

  • Root stack handles auth/modals.
  • (tabs) group for main navigation.
  • Dynamic routes like post/[id] for details.

6. Authentication Flow Architecture

Use protected routes in Expo Router v5+:

  • Root _layout checks auth state and redirects.
  • Splash screen until auth loads (use SecureStore or similar for tokens).
  • Separate (auth) and (app) route groups.
  • Context/Provider for user/session state.

Common stack: Clerk, Supabase Auth, or custom with JWTs + refresh logic.

7. State Management Strategies for Large Apps

  • Client state (UI, forms): Zustand (lightweight, slices) or Jotai.
  • Server state (API data): TanStack Query (caching, invalidation, background sync).
  • Global/complex: Redux Toolkit for very large teams.
  • Local persistence: MMKV + Redux Persist or WatermelonDB/SQLite for heavy offline.

Combine with React Compiler for automatic memoization optimizations.

8. API Handling and Networking Layers

  • Centralized API client (Axios/Fetch wrapper) in services/api.ts.
  • TanStack Query for mutations/queries with optimistic updates.
  • Interceptors for auth tokens, retries, and error handling.
  • Code generation for types (e.g., from OpenAPI).

9. Realtime Systems

  • Chat (WhatsApp-like): Supabase Realtime, Socket.io, or Stream Chat. Use WebSockets + optimistic UI + background sync.
  • Live updates: TanStack Query subscriptions or dedicated realtime DB.
  • Ride tracking (Uber): expo-location + WebSockets for driver position. Map with react-native-maps. Polling fallback for reliability.

Handle reconnections, message ordering, and delivery status carefully.

10. Offline-First Support and Caching

  • Storage: Expo SQLite / WatermelonDB or Realm for complex data.
  • Sync: TanStack Query + custom queues or libraries like PowerSync.
  • NetInfo for connectivity detection.
  • Cache images/media with expo-file-system.
  • Optimistic updates + conflict resolution on reconnect.

Instagram feed and Netflix downloads thrive on this.

11. App Startup Optimization Techniques

  • Splash screen until critical data/auth loads.
  • Async routes and lazy loading in Expo Router for code splitting.
  • Preload critical assets.
  • Minimize JS bundle (tree shaking, React Compiler).
  • Deferred non-critical initialization.

12. Performance Considerations in Production Apps

  • Use React.memo, useMemo, useCallback.
  • FlatList with proper keyExtractor and getItemLayout.
  • Reanimated for smooth animations (worklets on UI thread).
  • Image optimization (expo-image).
  • Monitor with Sentry/Flipper.
  • Enable New Architecture where possible.

Test on low-end devices.

13. Shared Layouts and Nested Routing in Expo Router

Layouts wrap children and persist state across navigation. Perfect for:

  • Persistent tab bars.
  • Auth wrappers.
  • Theme providers.
  • Custom headers that change per route.

Nested stacks inside tabs handle modals and details seamlessly.

14. Scalability Challenges in Specific Apps

  • Instagram: Infinite feeds (virtualized lists + pagination), media-heavy (caching/preloading), stories (horizontal carousels + realtime). High engagement needs excellent scroll performance.
  • WhatsApp: End-to-end encryption (handle on backend), massive realtime messaging scale, media sharing, groups, status. Reliability over everything.
  • Uber: Geolocation accuracy, real-time matching/tracking, payments, maps integration. Safety and low-latency critical.
  • Netflix: Video streaming (background playback), personalized recommendations (caching), profiles, offline downloads. Smooth UI for catalogs.

Expo Router handles their navigation patterns elegantly with groups and nesting.

15. Tradeoffs and Architectural Decisions at Scale

  • File-based vs Config: Expo Router enforces structure (good for teams) but less flexible than pure React Navigation.
  • Monolith vs Micro-frontends: Feature modules allow incremental scaling.
  • Native Modules: For heavy perf (maps, video), use Expo modules or custom.
  • Backend Choices: Supabase/Firebase for speed vs custom for full control.
  • Testing: Unit (Jest), component (Testing Library), E2E (Maestro/Detox).
  • Monorepo: Turborepo/Nx for shared packages across apps.

Tradeoff Example: Zustand for simplicity vs Redux for debugging tools in huge teams.

Conclusion: Building Like the Big Apps Today

With Expo Router + modern stack (TypeScript, TanStack Query, Zustand, Reanimated, SQLite), a small team can build apps rivaling giants in architecture and UX. Focus on modularity, performance from day one, and user-centric features.

Start with a solid folder structure and protected layouts — the rest scales naturally.

Recommended Reading:

  • Expo Router Docs
  • Feature-based architecture guides

Top comments (0)