polycratia

The smallest bug in a money system is a rounding call that nobody owns.

Split a repayment across several investors by share and you get fractions. Round each share to the currency's minor unit and the parts stop summing to the whole. One unit is left over, on every split, not once in a while.

It ships because nothing looks wrong. Every row is correct to two decimals. No exception, no failed request, no alert. The defect lives in the aggregate, and there is no single record you can point at and call incorrect.

Then the remainder goes somewhere. Whichever write lands last absorbs it, or it gets folded into a balance update, or it quietly disappears. A few thousand distributions later your ledger is internally consistent and externally wrong, and the first real signal is a reconciliation break far downstream, nowhere near the line that caused it. By then you are not asking how to fix the allocator: you are asking how to restate history.

So I treat distribution as a conservation operation rather than arithmetic. Amounts in integer minor units, never floats. Allocation of the leftover unit is deterministic, with an explicit tie-break, so the remainder has a named owner instead of a lucky one. Then an assertion before commit: the sum of the parts must equal the input, or the transaction fails loudly.

That last check carries most of the weight. Money code should be structurally unable to lose a unit in silence, because the cheapest place to catch drift is the function that created it: every layer after that only makes it more expensive to prove what happened.

I write more about designing invariants like this on my blog: https://polycratia.com/c/1c83664a

Where you enforce conservation is the part I keep going back and forth on: inside the allocator, or at the ledger boundary...

react

$ new-project --brief

or email hey@polycratia.com