- Why not just use Mint
- The capability model
- The importer is the whole problem
- Rules: classification at scale
- The queries that actually matter
- A note on privacy and backups
- Takeaways
Why not just use Mint
Mint died in 2024. Personal Capital pivoted to wealth-management upsell. Every replacement that lives in the cloud has one of two business models: sell you ads, or sell your transaction data to third parties as “anonymized” behavioral signal. The free product is the product. You are not.
Self-hosting a personal-finance ledger is the smallest possible privacy commitment you can make that still gives you the useful surface: a place to see every dollar, categorize it, and answer questions like “did I actually spend more on coffee this quarter than last?” without anyone else getting to read the answer.
Your transaction history is the most accurate diary of your life that exists. Decide who reads it. — Operating principle, finance domain
The capability model
The runtime is a private double-entry ledger with an import layer, a rules engine, a transaction store, and a review surface. The public page can describe the workflow without listing software, database shape, account count, or importer routes.
- Ledger renders dashboards, accepts transactions, and applies classification rules.
- Importer ingests bank exports and normalizes them into clean rows.
- Transaction store keeps the durable history inside the trust boundary.
- Cache keeps the UI responsive without exposing account context.
- Custom ingest handles the odd formats that banks do not document well.
PUBLIC VIEW
ledger live private route hidden
importer healthy bank map hidden
store private schema hidden
review gated SSO required
The importer is the whole problem
The ledger itself is largely undramatic. The real engineering is upstream: every American bank exports data in a slightly different shape, occasionally changes that shape without warning, and rarely publishes a stable schema. The importer absorbs that chaos and presents clean, deduplicated transactions to the ledger.
The mental model that finally worked:
- Per-account adapter. One module per bank. The module knows that bank’s download format, its date format, its quirks (negative-as-debit vs. amount-with-sign), and produces a normalized row.
- Dedupe on (account, date, amount, memo-hash). Banks sometimes re-issue a transaction with a different ID when a payment clears. The four-tuple is stable enough to catch dupes 99% of the time and human review handles the rest.
- Idempotent re-runs. Re-importing the same CSV must be a no-op. If it isn’t, you’ll spend a Saturday afternoon untangling double-counted rent.
Rules: classification at scale
Once transactions are in, classification is a problem you solve once and forget. The rules engine matches on description, amount, and source/destination account, then applies category, tag, and budget assignments.
IF description CONTAINS "wholefds"
AND amount > -800
THEN set category "Groceries"
add tag "WholeFoods"
assign budget "Food/Household"
About 90 rules cover roughly 95% of recurring transactions automatically. The remaining 5% are one-offs: travel, gifts, weird subscriptions, charges that need a memo. A weekly 10-minute review handles those.
The queries that actually matter
Five years of clean transaction data lets you answer questions that no cloud finance app was ever going to surface, because surfacing them doesn’t sell more ads.
- What categories drift slowly upward year over year? (Subscriptions, every time.)
- What recurring charges did I sign up for and forget? (Group recurring descriptions across the last year; the small ones are the dangerous ones.)
- What’s my real monthly run-rate, smoothed across quarterly bills? (Median of trailing 90-day windows.)
- What does a tax return actually look like before TurboTax tries to upsell me? (Filter by tag, group by category, dump CSV, hand to accountant.)
A note on privacy and backups
This is the most sensitive data in the private runtime. Storage is encrypted at rest, backups land in more than one place, and recovery credentials live outside the runtime with a plan that does not depend on the site being up.
Backup verification runs monthly: a restore drill loads a fresh copy into an isolated environment, runs sanity checks, and reports the result. A backup you haven’t restored is a wish.
Takeaways
Self-hosting a finance ledger isn’t about being clever with money. It’s about being clear-eyed with it. The clarity arrives slowly — the first year is just setup, the second year is rules-tuning, by year three the system tells you things you wouldn’t have noticed without it. Five years of clean data lets you read your own life back in numbers, and the numbers are surprisingly honest.
Total ongoing cost: about $1.50 / month in storage and zero dollars in subscriptions. The replacement cost in cloud-finance products would be roughly $180 / year and the loss of any control over who sees what.