Finance2025

Connecting real bank accounts, carefully

A personal finance app with live bank connections through Plaid, a tested service layer, and money stored the way money should be stored.

ProductBudgitify
RoleDesigner and engineer
Budgitify running on iPhone
Why this one is different

Touching someone's bank account raises the stakes on every decision in the codebase. A wrong number in a finance app is not a cosmetic bug, it is a person making a decision about their own money based on something untrue.

Bank data also arrives messy. Duplicate transactions, pending entries that change after the fact, inconsistent merchant names, and webhooks that fire more than once for the same event.

How I handled it

I treated correctness as the product. Money is stored as integer cents everywhere, so no balance has ever been subject to floating point drift, and the service layer has tests alongside nearly every file.

Plaid webhooks are verified before anything acts on them, and the sync path is written to be called twice without consequence, because eventually it will be.

What it does
  • Bank connections through Plaid, with OAuth institution support
  • A webhook pipeline with signature verification
  • A transaction sync and reconciliation service
  • A subscription detector that finds recurring charges
  • A user-defined transaction rule engine
  • Categorisation, budgets, goals, and net worth tracking
  • Encrypted storage for sensitive credentials
Correctness

Where the care went

01

Every amount is stored in whole cents

Never a float, at any layer, including in transit. It is the least interesting decision in the codebase and the reason a balance is never quietly off by a cent.

Correctness
02

Nothing acts on an unverified webhook

Every incoming Plaid webhook has its signature verified in middleware before any handler sees it. An endpoint that skips this is an unauthenticated write path into your data, and it is missing more often than you would expect.

PlaidSecurity
03

A rules engine users can actually drive

People want their own logic applied to their own transactions, so the rule engine lets them define it. The subscription detector finds recurring charges on its own, including ones people have forgotten they are paying for.

Rules engine
04

The tests sit where mistakes cost money

The service layer carries tests next to nearly every file: sync, categorisation, detection, net worth, goals, encryption. The tests are concentrated on the code where being wrong costs the user something real.

Testing
Where it landed

Budgitify is live on the App Store with real bank connections running in production, and none of the correctness work is visible to the person using it.

If you need financial data, bank connections, or anything where being slightly wrong is unacceptable, this is the relevant work.

Built with
Platform
SwiftUIKitWidgetKitStoreKit 2
Backend
NodeExpressTSOAPostgreSQLKnex
Infrastructure
Firebase AuthAWS SES
Services
Plaid