Independent SaaS · Serverless · Fintech

Bills, a Cash-Flow Projection App

Most budgeting apps tell you where your money went. Bills tells you where it will go: a daily balance projection up to a year ahead, with concrete strategies when the projection goes negative. In beta at bills-app.com; I build and operate it solo, outside my day job.

Role: Sole designer, builder, and operator

The problem

Budgeting apps are retrospective. They categorize last month's spending, but they can't answer the questions that actually cause financial stress: will I go negative before the next paycheck? What will my credit-card payment be two cycles from now? If I put an extra $200 toward this loan, what changes? I wanted a tool that treats personal finance as a forecasting problem, not an accounting one.

What I built

Bills is a serverless single-page app: a React 19 + TypeScript frontend talking to Python Lambdas behind API Gateway, with a single-table DynamoDB design and the whole stack defined in AWS CDK (five stacks: core, financial, extensions, integrations, monitoring). Bank data syncs through Plaid; subscriptions run on Stripe.

flowchart LR
SPA["React SPA
TypeScript · Amplify"] --> APIGW["API Gateway
Cognito auth"] APIGW --> L["~50 Python Lambdas
shared layer"] L --> DB[("DynamoDB
single-table")] PLAID["Plaid
bank sync webhooks"] --> L EB["EventBridge
daily crons"] --> L L --> PROJ["Projection engine
daily snapshots, 1 year out"] PROJ --> DB

Every money write triggers a projection chain: sync, snapshot, project forward, analyze patterns, alert.

The parts I consider real engineering, not CRUD:

Core
Projection engine

A deterministic simulator that walks day by day up to a year out, combining recurring rules (including last-business-day and nth-weekday recurrence), credit-card payments, loan amortization, budgets as daily spend rates, and equity vesting events with tax withholding. When it finds a future gap, it generates concrete payment strategies rather than just a warning.

Core
Credit-card cycle engine

A pure-compute model that answers "what will my payment be N cycles from now": closed cycles anchor to actual balance history at statement close, the open cycle anchors to the live balance adjusted for in-flight payments, and future cycles chain through projected spending and unpaid carry-over. Deferred-interest promos are modeled as payment plans so 0% financing never silently turns into interest.

  • Bank sync: Plaid webhooks drive transaction sync with deduplication fingerprinting, two-year backfill, reconnect handling, and loan-payoff detection. Balance refreshes piggyback on free Plaid endpoints rather than paid ones, a deliberate cost decision.
  • Categorization: a three-tier matcher (known entity, known description, similarity scoring) plus user-defined rules and bulk auto-categorization.
  • Imports: CSV with a review table, and PDF statement parsing.
  • Notifications: a daily digest across push, Telegram, and in-app channels, plus negative-balance and credit-limit alerts, all EventBridge-scheduled.
  • SaaS plumbing: Stripe subscriptions, an admin dashboard with metrics and beta-whitelist management, Cognito authentication with a pre-auth Lambda enforcing the beta list, data export, and a CloudWatch monitoring stack with alarms on errors, throttles, and latency.

How it's built (the process)

Bills is also my proving ground for AI-assisted, spec-driven development: every non-trivial feature starts as a written design spike (60+ dated documents with a shipped/archived lifecycle), a living architecture reference defines canonical primitives and banned patterns, and canary tests pin backend computations against the legacy frontend math they replaced. Roughly 100k lines of TypeScript and Python, 465 commits in the first five and a half months, versioned releases with a maintained changelog. I wrote about the philosophy in Show, Don't Tell.

Status

In beta with a whitelist, under active development. Bills is the system where I get to own every layer: product, frontend, backend, infrastructure, monitoring, and billing.

open_in_new Visit bills-app.com

arrow_upward