ArchitectureJune 3, 20261 min

Why I store money as integers

There's a bug that shows up in almost every app that handles money before someone stops to think about it: 0.1 + 0.2 === 0.30000000000000004. Floating point was never designed to represent currency, and the moment you start adding, splitting, and rounding amounts, the errors compound.

So on every project that touches money, I make the same early decision: store amounts as integers in the smallest unit — cents, or in Colombian pesos, just whole pesos.

The rule

  • The domain never sees a float.
  • An amount is an int in the smallest currency unit.
  • Formatting to $1,234.50 is a concern of the edges (the UI), never the core.

Why it matters

When money is an integer, equality is exact. "Is this plan settled?" becomes every balance === 0 — no epsilon, no "close enough". That single property makes the rest of the system honest: the split function can guarantee that sum(shares) === total, and the settle-up algorithm can trust the numbers it's handed.

This is the same idea as domain at the core, infrastructure at the edges. The representation that keeps the math correct lives in the center; the pretty, locale-aware string is a detail of the boundary.

It's a tiny decision. It's also the kind of decision that's painful to reverse once balances are wrong in production — so I make it on day one.

Related notes