Back to Journal
Mobile/Frontend

Cross-Platform Architecture at Scale: Lessons from Production

Real-world lessons from implementing Cross-Platform Architecture in production, including architecture decisions, measurable results, and honest retrospectives.

Muneer Puthiya Purayil 13 min read

In 2022, our fintech startup needed to deliver iOS, Android, and web applications for a digital banking product. With a team of seven engineers and a nine-month runway to launch, we chose React Native with Expo as our cross-platform foundation. Eighteen months later, the platform serves 340,000 users across all three platforms with a 4.7-star average app store rating. This case study covers the architecture, the trade-offs, and the lessons we would carry into the next build.

Starting Context

The product requirements were substantial for a startup: biometric authentication, real-time push notifications for transactions, offline access to account balances, document scanning for KYC, and PCI-compliant card management. The regulatory environment required separate security reviews for each platform deployment.

Team composition: three senior React engineers (no native mobile experience), two mid-level fullstack engineers, one designer, and one engineering manager. Budget for native iOS and Android development: zero.

Architecture Decisions

Framework: React Native with Expo

We chose React Native over Flutter for one reason: our entire team knew TypeScript and React. The learning curve for React Native was two weeks versus an estimated eight weeks for Flutter with Dart. At a startup, those six weeks matter.

Expo provided managed native modules for camera, biometrics, secure storage, and push notifications — capabilities that would have required native development experience without it.

Monorepo Structure

1banking-app/
2├── apps/
3│ ├── mobile/ # Expo managed workflow
4│ └── web/ # Next.js
5├── packages/
6│ ├── api/ # tRPC client + React Query
7│ ├── domain/ # Business logic, validation
8│ ├── store/ # Zustand stores
9│ └── ui/ # Shared components (Tamagui)
10 

We used Turborepo for orchestration. The packages/domain directory contained all business rules — transaction categorization, spending limit calculations, account balance aggregation — running identically across platforms.

UI Framework: Tamagui

Tamagui gave us a single component library that rendered native views on mobile and optimized HTML on web. This was the highest-leverage decision we made — it enabled genuine UI code sharing (72% of UI components) without the uncanny valley effect.

typescript
1// packages/ui/components/TransactionCard.tsx
2import { Card, H4, Paragraph, XStack, YStack } from 'tamagui';
3 
4export function TransactionCard({ transaction }: { transaction: Transaction }) {
5 return (
6 <Card padded bordered>
7 <XStack justifyContent="space-between" alignItems="center">
8 <YStack>
9 <H4>{transaction.merchantName}</H4>
10 <Paragraph theme="alt2">{transaction.category}</Paragraph>
11 </YStack>
12 <Paragraph
13 color={transaction.amount < 0 ? '$red10' : '$green10'}
14 fontWeight="600"
15 >
16 {formatCurrency(transaction.amount, transaction.currency)}
17 </Paragraph>
18 </XStack>
19 </Card>
20 );
21}
22 

Data Layer: tRPC + React Query

tRPC provided end-to-end type safety from the backend API to the mobile client. React Query handled caching, background refresh, and offline support.

typescript
1// packages/api/client.ts
2import { createTRPCReact } from '@trpc/react-query';
3import type { AppRouter } from '@banking/backend/src/router';
4 
5export const trpc = createTRPCReact<AppRouter>();
6 
7// Usage in any platform
8function AccountScreen() {
9 const { data: balance } = trpc.accounts.getBalance.useQuery(
10 { accountId: activeAccountId },
11 { staleTime: 30_000 } // 30s cache
12 );
13 
14 const { data: transactions } = trpc.transactions.list.useQuery(
15 { accountId: activeAccountId, limit: 50 },
16 { staleTime: 60_000 }
17 );
18 
19 return (
20 <YStack>
21 <BalanceCard balance={balance} />
22 <TransactionList transactions={transactions} />
23 </YStack>
24 );
25}
26 

Code Sharing Results

After 18 months of development:

LayerCode Sharing %
Business Logic98%
API Client100%
State Management95%
UI Components72%
Navigation0% (platform-specific)
Native Modules15% (wrappers shared)
Overall68%

The 68% overall sharing translated to roughly 2.5x developer productivity compared to building three separate applications.

Need a second opinion on your mobile/frontend architecture?

I run free 30-minute strategy calls for engineering teams tackling this exact problem.

Book a Free Call

Measurable Results

MetricTargetActual
Time to launch (all platforms)9 months11 months
App store rating (average)4.54.7
Cold start time (iOS)< 2s1.4s
Cold start time (Android)< 3s2.1s
Crash-free sessions> 99.5%99.7%
Monthly active users (month 6)100K142K
Engineers required77 (no additional hires)

What Failed

Expo Managed Workflow Limitations

At month four, we needed custom native module integration for a third-party card SDK that Expo's managed workflow did not support. The ejection to a bare workflow cost us two weeks of engineering time and introduced native build complexity that the team was not prepared for. We should have started with the bare workflow from the beginning.

Web Performance

React Native Web (via Tamagui) produced larger JavaScript bundles than a native Next.js application would have. Initial web load time was 4.2 seconds — unacceptable for SEO and user acquisition. We ended up rebuilding the marketing pages and onboarding flow as pure Next.js pages, reserving the React Native Web runtime for the authenticated dashboard. This split architecture added complexity but reduced web load time to 1.8 seconds.

Platform-Specific Gesture Handling

Our custom swipe-to-pay feature required different gesture implementations on iOS (UIKit gesture recognizer bridged) and Android (native gesture handler). The shared gesture abstraction we built was fragile and broke across React Native versions. We should have accepted platform-specific implementations for gesture-heavy features from the start.

Honest Retrospective

Would we choose React Native again? Yes, for this team composition. The TypeScript/React expertise of the team was the deciding factor, and it proved correct.

What would we change?

  1. Start with Expo bare workflow, not managed
  2. Build the web marketing funnel as pure Next.js from day one
  3. Invest in E2E testing (Detox for mobile, Playwright for web) in month one, not month six
  4. Hire one engineer with native iOS/Android experience by month three
  5. Use React Navigation's native stack everywhere — we initially used JS-based stack for "consistency" and the performance difference was noticeable

What surprised us?

Android performance was significantly better than expected. React Native's Hermes engine on Android often outperformed iOS's JavaScriptCore for our computation-heavy transaction categorization logic. We had allocated extra Android optimization time that we did not need.

Conclusion

Cross-platform development with React Native enabled a seven-person team to ship a production banking application to iOS, Android, and web in 11 months. The 68% code sharing rate translated directly into reduced engineering headcount requirements — our estimate for building three native applications was 12-15 engineers. The trade-offs were real: web performance required architectural splits, gesture-heavy features needed platform-specific implementations, and Expo's managed workflow hit limitations sooner than expected.

For startups with React/TypeScript teams building content-heavy or form-heavy applications, React Native remains the highest-ROI cross-platform choice. For gesture-intensive or graphics-heavy applications, evaluate Flutter's rendering engine or native development more seriously.

FAQ

Need expert help?

Building with mobile/frontend?

I help teams ship production-grade systems. From architecture review to hands-on builds.

Muneer Puthiya Purayil

SaaS Architect & AI Systems Engineer. 10+ years shipping production infrastructure across fintech, automotive, e-commerce, and healthcare.

Engage

Start a
Conversation.

For teams building at scale: SaaS platforms, agentic AI systems, and enterprise mobile infrastructure. Scope and fit are evaluated before any engagement begins.

Limited availability · Q3 / Q4 2026