Skip to main content
Special EditionFull Stack

"Ledgerly" — Shared Expenses Without the Arguments

Screenshot of Ledgerly

A shared-expense tracker for flatmates and trips. Balances are derived from an append-only ledger rather than stored, settlements are idempotent so a double-tap never double-pays, and the "who owes whom" graph is simplified to the fewest possible transfers. (Sample project — replace with your own.)

Tech Stack
Next.jsTypeScriptPostgreSQLPrismaStripeTailwind CSS
My role
Solo — data model, settlement logic, interface
Built for
Sample case study · replace with your own

“When you can store the evidence instead of the conclusion, store the evidence.”

I.

The Brief

Shared expenses sound simple until two people add a bill at the same moment, a request is retried, or someone settles up while a third person edits an old expense. Balances stored as numbers drift.

The second problem is human: with six people and forty expenses, "who pays whom" has dozens of valid answers, and most of them involve too many transfers.

II.

The Approach

Ledgerly stores an append-only ledger of expenses and payments and derives every balance from it. Nothing is edited in place; a correction is a new row that reverses the old one.

Settling up runs a greedy matching over net balances — largest creditor against largest debtor — which keeps the number of transfers at or near the minimum for typical groups.

III.

How It Works

  1. 01Clientadds an expense with an idempotency key
  2. 02APIvalidates, writes one ledger row
  3. 03PostgreSQLunique key makes retries harmless
  4. 04Balancessummed from the ledger
  5. 05Settlefewest-transfers plan
IV.

Key Decisions

Idempotency keys on every write

A unique index on the client-generated key turns double-taps and retries into a single row.

Money as integers

Amounts are stored in the smallest currency unit, with explicit rounding rules for uneven splits.

A rebuildable summary

A materialised balance table speeds up large groups and can be dropped and rebuilt from the ledger at any time.

1
row per fact — nothing edited in place
≤ n−1
transfers to settle n people
Known limits — stated plainly
  • Sample case study — replace with a real one.
  • Multi-currency groups convert at entry time and do not revalue later.