Money has more than two decimals
The first rule of money in software is well known: never use floats. The second is less known, and it’s the one that bites in this region: never assume two decimal places. Two platforms I built — a licensure and tutoring platform and a ride-hailing system — both had to get this right, in opposite directions.
Integer minor units, plus the currency’s own exponent
Both store money as integer minor units plus a currency code. The detail that matters is the exponent: how many minor units make one major unit. It’s two for USD, and it’s three for JOD, KWD, BHD, OMR and TND. One Jordanian dinar is a thousand fils.
Hardcode two decimals and every price, invoice and payment-gateway call for a dinar-denominated customer is off by a factor of ten — not occasionally, always. The fix isn’t clever. Each currency carries its exponent, and nothing formats, converts or sends an amount without asking for it.
Two rules that fell out of it
- Cast
bigintaggregates at the boundary. PostgreSQL returns the sum of abigintcolumn as a numeric, which most drivers hand you as a string. Add that to an integer in application code and you get concatenation or a silent coercion, depending on the language. Cast once, where the value enters your code. - Never sum a money column without scoping by currency. 100 USD plus 100 JOD is not 200 of anything. A dashboard total that forgets the currency filter isn’t slightly wrong; it’s meaningless, and it looks perfectly plausible.
Disagreeing with ISO on purpose
The ride-hailing platform runs in a cash-first market, and there I made the opposite call: EGP is stored with zero minor units. ISO says two. But the rider hands over notes, nobody makes change in piastres, and the fare rounds to the nearest five pounds anyway. Modelling piastres would mean carrying precision that no transaction will ever use, and inviting a fare of 47.35 that no driver can actually collect.
That’s the real lesson. The exponent isn’t a formatting detail you look up once; it’s a statement about how money actually moves in that market. Sometimes the standard describes it, and sometimes the street does.
The principle
Money is a value and its unit, and the unit has more properties than its symbol. Model the unit, carry it everywhere, and make every operation that combines amounts prove they share it.