SplitPro

Self-hosted, open source expense splitting with multi-currency, recurring bills, and bank imports — a complete Splitwise replacement you control.

1.3Kstars
175forks
MIT License
TypeScript

SplitPro is a self-hosted open source alternative to Splitwise, built for individuals and groups who want full ownership of their financial data. It covers the entire expense-management workflow: add expenses with multiple split methods, track per-person and per-group balances, settle debts, and receive push notifications when new charges arrive.

Version 2.0 introduced a fundamental architectural shift: balances are now computed on the fly from PostgreSQL views rather than maintained in a separate table. This eliminates an entire class of stale-balance bugs and unlocks recurring expenses powered by pg_cron. Multi-currency conversion with pluggable rate providers and Plaid bank-transaction import round out the feature set for households with complex financial lives.

The stack is entirely TypeScript — Next.js 15 on the frontend, tRPC for type-safe API communication, Prisma with PostgreSQL for data persistence, and Serwist (Workbox) for PWA and offline capability. All monetary values are stored as BigInt to prevent floating-point rounding errors, and leftover pennies from uneven splits are distributed deterministically across participants.

Deployment is designed for self-hosters: a Docker Compose file with the custom ossapps/postgres image (which bundles the pg_cron extension) is the recommended path, and the Dockerfile produces a lean Alpine-based production image. Authentication relies on NextAuth with email magic links, Google OAuth, and generic OIDC support for Authentik, Keycloak, and GitLab, making it easy to integrate with existing identity infrastructure.

What You Get

  • Flexible Expense Splitting - Split any expense by equal share, percentage, exact amounts, share weights, or per-participant adjustments, with full support for negative expenses (refunds) and deterministic leftover-penny distribution to avoid rounding disputes.
  • Database-Computed Balances - Group and per-person balances are derived from PostgreSQL views rather than maintained tables, eliminating stale-balance bugs and making the expense record the single source of truth across all views.
  • Multi-Currency Conversion - Track expenses in any currency and convert group balances on the fly using pluggable rate providers (Frankfurter, Open Exchange Rates, or NBP), with rates cached in the database to minimise API calls.
  • Recurring Expenses via pg_cron - Schedule repeating bills (rent, subscriptions, utilities) using standard cron expressions; the PostgreSQL pg_cron extension creates derived expense records automatically while preserving the ability to edit or delete individual occurrences independently.
  • Plaid Bank Transaction Import - Connect a bank account via Plaid, browse fetched transactions, and convert them into SplitPro expenses in bulk, with duplicate detection to prevent double-entry.
  • PWA with Push Notifications - Install SplitPro as a Progressive Web App on any device and receive real-time push notifications powered by the Web Push API and Serwist service worker when new expenses, edits, or settlements are recorded.
  • Multiple Auth Providers - Sign in via email magic link, Google OAuth, or any OIDC-compatible provider (Authentik, Keycloak, GitLab); username/password is intentionally not supported to keep the attack surface minimal.
  • Splitwise Migration Utilities - Import existing friends and groups from a Splitwise export to rebuild your network without starting from scratch, with data export available from balances and account settings.

Common Use Cases

  • Shared apartment cost tracking - Roommates deploy SplitPro on a home server or VPS and use the equal-split and exact-amount modes to divide rent, utilities, and grocery runs, with monthly summaries and receipt uploads for full transparency.
  • Multi-currency group travel - A group travelling across several countries adds expenses in local currencies, converts balances to a single home currency using a configured rate provider, and settles up at the end of the trip with minimal rounding disagreements.
  • Automated recurring household bills - A family sets up recurring expenses for Netflix, internet, and insurance using pg_cron-backed cron rules so monthly charges appear automatically without anyone needing to remember to log them.
  • Privacy-first Splitwise replacement - A privacy-conscious user migrates from Splitwise, imports their friend network via the CSV import tool, and moves to SplitPro to avoid data monetisation and subscription upsells on core features.
  • Home-lab OIDC integration - A self-hoster configures SplitPro behind Authentik or Keycloak for single sign-on, restricts signups to invited users only, and locks down the instance with environment variables to prevent public registration.

Under The Hood

Architecture SplitPro follows a clean layered architecture built on the T3 stack principles: Next.js pages and React components handle presentation, tRPC routers expose typed server procedures grouped by domain (expenses, groups, users, bank transactions), and a service layer (splitService, currencyRateService, notificationService, scheduleService) encapsulates business logic away from transport concerns. The tRPC context injects the Prisma client and the authenticated session into every procedure, providing consistent data access without manual dependency wiring. A central architectural decision — migrating balances from stored tables to PostgreSQL computed views — moves financial truth into the database layer and eliminates an entire class of consistency bugs that plagued the v1 architecture. Environment configuration is validated at startup via Zod schemas from @t3-oss/env-nextjs, preventing misconfigured containers from running silently.

Tech Stack The application is written entirely in TypeScript and runs on Node.js 22 inside an Alpine Docker image. Next.js 15 with Turbopack powers the frontend using the legacy pages router, while tRPC v11 and React Query v5 provide end-to-end type-safe client-server communication. Prisma 6 manages the PostgreSQL schema, migrations, and query building. The UI layer combines Tailwind CSS v4, Radix UI primitives, and class-variance-authority for composable, themeable components. Serwist (a maintained Workbox fork) registers the service worker for PWA offline support and Web Push delivery. The custom ossapps/postgres Docker image bundles the pg_cron extension required for recurring transactions. PLpgSQL migrations express recurring-expense scheduling and balance view logic directly in the database.

Code Quality The codebase maintains a targeted but meaningful test suite: Jest covers the core financial algorithms (debt simplification, cron timezone transformation, number formatting) with exhaustive property-based and example-based cases that verify balance conservation, metadata preservation, and edge-case handling. Error handling in service functions follows explicit async/await patterns with descriptive thrown errors rather than swallowed exceptions. Type safety is enforced end-to-end through Prisma-generated types, tRPC procedure signatures, and Zod input validators on every route. Linting uses oxlint with type-aware mode and lint-staged/husky pre-commit hooks for consistency. The absence of integration tests for API routes and the service layer is the main quality gap — financial logic is well-covered but HTTP-layer behaviour relies on manual validation.

What Makes It Unique The most distinctive technical choice is the shift to PostgreSQL views for balance computation, a departure from the industry-standard approach of maintaining running totals in application code. This design makes the database the arbiter of financial state and enables recurring transactions to insert expense rows via pg_cron SQL procedures without any application coordination. The timezone-aware cron transformer (tested with edge cases for midnight crossings, month boundaries, and day-of-week rollover) converts user-local cron expressions to UTC before persisting to pg_cron — a subtle but correctness-critical detail most scheduling systems overlook. The abstract CurrencyRateProvider class with a shared caching layer and pluggable concrete implementations (Frankfurter, Open Exchange Rates, NBP) lets operators choose between coverage and cost without code changes. BigInt storage for all monetary values eliminates floating-point precision loss even for currencies with large nominal values.

Self-Hosting

SplitPro is released under the MIT License, which grants unrestricted rights to use, modify, distribute, and run the software commercially. There are no copyleft obligations — you can deploy it inside a private network, fork it for a commercial product, or bundle it in a larger offering without publishing your modifications. The only requirement is preserving the copyright notice.

Running SplitPro yourself requires a PostgreSQL database (with the pg_cron extension if you want recurring transactions), a persistent volume for receipt uploads, and a Node.js container for the application. The project ships a production Docker Compose file that wires these together, including the ossapps/postgres image with pg_cron pre-installed. You are responsible for database backups, volume persistence, TLS termination (typically via a reverse proxy), and applying future migrations — each tracked in the prisma/migrations directory and deployed automatically on startup via prisma migrate deploy. Operational complexity is moderate for a single-instance deployment but grows if you need high availability, since there is no built-in clustering support.

There is no official hosted or managed tier — SplitPro is purely self-hosted. This means no out-of-the-box SLAs, no managed upgrades, and no vendor support channel beyond community GitHub issues and discussions. A community-run instance at splitpro.app was frozen at v1.3.4 and is no longer maintained. What you gain over SaaS alternatives is complete data ownership, no subscription fees, no feature gating, and the ability to integrate with your existing identity provider via OIDC — making it a good fit for privacy-conscious users or organisations that already operate their own infrastructure.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack

No spam. Unsubscribe anytime.

Join 750+ subscribers
No spam. Unsubscribe anytime.

Search