← All work
05Own product · 2026

APM SaaS.

The books of a parent-teacher association, with rules the database itself enforces.

RLS on 33 tablesImmutable ledgerTestcontainers
The association’s cash view with balance, receivables, payables and the list of installments

The problem

A school’s parent-teacher association handles families’ money, changes its board every term and has to account for the money. Contributions are membership dues, not tuition. The data is about students, so Brazil’s data protection law (LGPD) applies. If an entry can be edited later, nobody trusts the balance anymore.

What I built

I wrote all of it: cash book, contributions, projects, bank statement import with an OFX parser, financial reports and the handover from one board to the next. Notifications respect a quiet window from 9 p.m. to 8 a.m. The most important rules are not in the application code. They live in the database, and the tests fail if anyone forgets them.

Technical decisions

  1. 01Rules live in the database

    33 tables with FORCE ROW LEVEL SECURITY, 38 policies, 11 SECURITY DEFINER functions, 3 constraint triggers and one EXCLUDE constraint. If the app has a bug, Postgres still rejects data that breaks a rule.

  2. 02A ledger you cannot edit

    Entries are never changed or deleted. A correction is a reversal, and it stays in the history. Money is stored as integer cents. No floating point, no cents lost to rounding.

  3. 03Tests that check every table

    rls.test.ts fails if any table has no policy, and audit.test.ts fails if any table has no audit trail. A new table cannot slip in unprotected because someone forgot. The tests run against a real Postgres through Testcontainers.

    Where it lives in the code: rls.test.ts · audit.test.ts

  4. 04No HTTP calls inside a transaction

    Anything that has to leave the system goes into an outbox and is handled by pg-boss jobs, outside the transaction. Jobs are idempotent, and a test runs them again to prove it. A slow external API cannot hold a database lock, and a retry does not duplicate anything.

Numbers

31

commits, single author

~165

tests

37

tables

15

migrations

Stack

  • TanStack Start
  • React 19
  • Better Auth
  • PostgreSQL
  • Drizzle
  • Zod 4
  • Tailwind 4
  • pg-boss
  • Vitest
  • Testcontainers
  • Playwright

Screens

Membership dues charged per family, with a sibling discount
Financial report for the period, with income, expenses, the result and the report’s fingerprint
Next case

CRM Next