A behind-the-scenes look at the technologies powering Finaps — from our NestJS backend and Expo mobile app to our AI pipeline and offline-first architecture.
Building a finance app that works across iOS, Android, and the web while maintaining a delightful user experience requires careful technology choices. Today, we're pulling back the curtain on the stack that powers Finaps.
Our monorepo is built with pnpm workspaces and Turborepo, allowing us to share code across four applications (API, mobile, web, admin) and six packages (UI components, API client, shared types, utilities, internationalization, and configuration). This architecture means a change to our shared types package automatically propagates to every application that uses it.
The backend runs on NestJS with Fastify, chosen for its modular architecture and excellent TypeScript support. MongoDB Atlas serves as our primary database — its flexible document model is ideal for financial data that varies significantly across users, currencies, and account types. Redis handles caching, session management, and serves as the backend for BullMQ, our job queue for background processing.
The mobile app is built with Expo SDK 52 and React Native, using Expo Router v4 for file-based navigation. NativeWind v5 gives us Tailwind CSS classes that work natively on both iOS and Android, meaning our designers can use the same design tokens across all platforms. For charts, we use Victory Native XL with Skia rendering for smooth 60fps animations.
Offline-first was a non-negotiable requirement. Finance apps must work without internet — you should be able to log expenses on a subway or in a foreign country with poor connectivity. We use expo-sqlite with WAL mode for local storage, maintaining a sync queue that resolves conflicts using a server-authoritative strategy when connectivity returns.
Our AI pipeline is designed for reliability and cost efficiency. GPT-5 mini handles primary AI tasks (categorization, chat, insights), with Anthropic Claude Sonnet as a fallback when the primary provider has issues. A circuit breaker pattern prevents cascade failures, and our three-tier categorization system (rule engine, ML heuristic, LLM) ensures that AI costs stay manageable by only invoking expensive LLM calls when simpler methods fail.
The web app uses Next.js 15 with the App Router, leveraging server components for optimal performance and SEO. The admin panel is a separate Next.js application with its own security model — admin auth cookies are never shared with the user-facing app.
For payments, we use a dual approach: Stripe handles web subscriptions directly, while RevenueCat manages mobile subscriptions through the App Store and Play Store. This separation is necessary because Apple and Google require in-app purchases for digital subscriptions on their platforms.
Every piece of this stack was chosen with a specific rationale, and we're constantly evaluating new tools and techniques. If you're building something similar, feel free to reach out — we love talking about engineering challenges in fintech.