Files
web_sport/docs/adr/0011-money-as-integer-minor-units.md
T

1.1 KiB

ADR-0011: Money as integer minor units

  • Status: Accepted
  • Date: 2026-08-11

Context

0.1 + 0.2 !== 0.3. Floating-point money produces discrepancies that are invisible in testing and unfixable once they are in an order history.

Decision

All monetary values are integers in the currency's minor unit, in the database (priceAmount Int), across the API ({ amount, currency }), and in TypeScript (Money). VND has a minor-unit scale of 0, so 250000 means ₫250.000. Conversion to a display string happens in exactly one function, formatMoney, using Intl.NumberFormat.

Consequences

Arithmetic is exact. No conversion happens between layers because every layer holds the same integer. Multi-currency is already representable without a schema change.

Developers must remember that price.amount is not a display value; the single formatter and the absence of any other division by 100 are what keep that from going wrong.

Alternatives considered

Decimal/numeric columns — correct in the database but arrive in JavaScript as strings or a Decimal object that must be handled at every boundary. Floats — never.