Money is a decimal string
Every monetary amount on the wire is a decimal string. Never a float, never cents-as-integer. The one rule that prevents the worst class of bug.
Every monetary amount on every surface — a price, a payoff, a payment, a
ceiling — is a decimal string: "24990.00", not 24990.0 and not 2499000.
{ "amount": "492.00", "currency": "USD" }Why
- Floats lose money.
0.1 + 0.2is not0.3in binary floating point. A records office does not round the customer's money in a way it cannot attest. - A string is exact and self-describing.
"492.00"carries its own scale; there is no ambiguity about whether a number is dollars or cents, and no locale reinterprets it. - It survives the wire and the receipt. The same bytes render in JSON for an agent and in a plain-language receipt for the person whose money is moving — the twin invariant applied to money.
The rule
- Parse decimal strings with a decimal library, never
parseFloat. - Compare and sum as decimals; format for display only at the edge.
- A price is a field, not a conversation. Where a price is not yet set, the
catalog row says
declaredand points at/pricingrather than inventing a figure — posted or declared, never a number the estate cannot stand behind.
Review before acting
Financial figures — payoffs, quotes, rates, out-the-door math — are attested with source and date, and should be reviewed before any decision that moves money. The caveat is stated plainly and once, never scattered as hype.