Mizan
A private multi-currency household finance system built around an immutable ledger, explicit planning, and explainable balances.
- Status
- In production
- Source
- Public description
- Evidence
- Architecture · Data model · Data flow · Worker design · Failure design · Workflow · Screenshots
- Stack
- TypeScript · Next.js · React · PostgreSQL · Drizzle ORM
01
Overview
What this is
Mizan is a private household finance system built for two people managing money across USD, KWD, and IDR. It combines everyday transactions, accounts, budgets, reserved buckets, recurring commitments, scheduled payments, and reporting without flattening every number into a single currency or hiding how a balance was produced.
The interface is intentionally calm; the harder work lives beneath it. Transactions are modeled through immutable revisions and balanced ledger postings, currency conversions keep their rates and provenance, and planned items remain plans until an explicit settlement creates financial history.
Built for my household and used by two people across three currencies. The public case study and every screenshot use synthetic data only.
The problem
Generic trackers did not match the household’s combination of shared ownership, multi-currency balances, reserved money, and future commitments. A useful replacement had to be simple in daily use while making corrections, conversions, and automation trustworthy enough to explain later.
What I built and owned
I defined the product and accounting semantics, designed the responsive interface, built the modular Next.js application and PostgreSQL schema, implemented authorization, automation, reporting, and recovery controls, and operate the private deployment.
The running application and source are private. Every screenshot on this page comes from a disposable database containing only synthetic people and transactions; no production data, account names, balances, or URLs are shown.
02
Detail
How it works
Trust comes from the model
Mizan treats the original currency as canonical and preserves settlement and reporting conversions as separate, traceable facts. Monetary values use exact decimals rather than binary floating point. A correction never rewrites history in place: it creates a new revision and new balanced postings, preserving the path from what was entered to what is now considered current.
That exactness is deliberately kept out of the way during ordinary use. The interface speaks in accounts, expenses, transfers, buckets, budgets, and upcoming commitments; the ledger remains available as the reason a balance can be trusted.
Everyday on top, exact underneath
- 01
Native currency stays visible
USD, KWD, and IDR balances remain first-class while reporting conversions retain their rate and provenance.
- 02
Planning cannot become history by accident
Recurring and scheduled commitments affect forecasts, but only an explicit settlement creates a financial transaction.
- 03
Buckets reserve; they do not mint money
Allocations change what is spendable without changing the underlying account balance.
- 04
Every request is household-scoped
Authorization follows the household and member context rather than trusting a record identifier from the browser.
3 images · select one to open the full view
Diagram · select to open the full view
Text description of this diagram
Two members use one responsive, household-scoped application for accounts, transactions, budgets, buckets, upcoming commitments, and reports. Financial commands pass through authorization and domain rules before they create immutable transaction revisions, journals, and balanced postings in PostgreSQL. Exact decimals and exchange-rate provenance preserve the financial truth.
Recurring and scheduled commitments are stored as planning records rather than ledger entries. When a member explicitly settles one, the application creates the corresponding financial history. Background effects travel through an outbox to an idempotent scheduled worker, which records failures and supports safe retry.
The screenshots were captured from a fresh disposable PostgreSQL database populated with fictional people, accounts, balances, budgets, buckets, and transactions. No production database, development database, private URL, or real financial record was used.
03
Result
What came of it
04
Links
Where to look
Something similar in mind?
If this is close to a problem you have, the fastest thing is usually a short conversation about what you are actually trying to change.
Discuss a project