In a payment system the most expensive bug is usually a rounding rule nobody wrote down.
Take one repayment split across several investors by share. Every line looks correct, and every line is correct. The sum is not: off by a cent, in a direction that depends on the ratios.
Nothing throws. No test fails either, because the tests assert on a single record, and a single record is fine. The defect exists only in the aggregate, and the aggregate is what the bank settles against.
That asymmetry is what makes it costly. A crash is loud and local. A cent of drift is quiet and compounding: enough distributions later your ledger and the settlement disagree, reconciliation starts flagging rows that are each individually defensible, and you lose the ability to tell drift from something worse. Money systems are append-only, so you don't fix it forward. You correct history, and someone has to decide who absorbed the cent.
So I settle this at design time instead of leaving it to the implementation. Amounts as integer minor units, no floats. The remainder policy gets written out too: largest remainder, assigned to a named party, specified in the spec rather than inherited from whatever rounding mode the language defaults to. Then an invariant at the boundary, where the split has to sum back exactly to the input before anything is persisted.
The general shape is worth keeping. A bug that is wrong only in aggregate is more dangerous than one that crashes, because your test suite and your error tracker are both built to see the second kind.
I write up more of these production trade-offs on my blog, if that's useful: https://polycratia.com/c/ab24a2cb
Worth knowing which part of your system decides the rounding: the schema and the spec, or whichever language touched the number last...