Part 7
Data, migrations, and money
7.1 The schema, and changing it safely
Your database has a structure: tables, columns, relationships. A migration is a versioned change to that structure, one file that adds a table, a column, an index. The safe pattern, worth copying: a read-only step first that checks the current state without writing anything (do the target tables already exist, do the things I depend on exist). If the read-only step surprises you, stop before you write. Then the writing step, wrapped so it either fully applies or fully rolls back, never half.
For the CTO in you
lock the database down by default. Turn on row-level security on every table, and let only the server-side role read and write. The frontend never touches the database directly; everything goes through the backend. A table with security off is a door you forgot was open.
7.2 Money is stored in the smallest unit
Never store money as a rounded decimal. Store it in the smallest unit, as a whole number of cents. Decimals drift and round in ways that quietly create money or lose it. This is not pedantry, it's the difference between books that balance and books that don't.
7.3 Idempotence: the same event twice, one effect
Third parties will send you the same event twice: a payment webhook gets replayed, a request retries. If "payment received" runs twice, you must not credit twice. The common guard is a uniqueness constraint, a unique identifier on the event, so the second arrival is silently ignored. Design for replay, because replay will happen.
7.4 Proving a mass data change
When you change data at scale, you prove it with an invariant, not a re-read (Law 6). After a bulk update, check that the counts match and zero of the old form remains. Before and after a big migration, prove that the rows that shouldn't have moved are byte-for-byte identical. And prove the result on the real data as a delta: these numbers moved from X to Y, and nothing landed where it shouldn't. A green test says "my code ran." A delta says "the world changed the way I intended."