Money representation
Why Axerity stores amounts as BigInt minor units, and why you should too.
Internally, Axerity stores every monetary amount as a BigInt of the currency's minor units. For USD, that's cents. For JPY, it's yen. For BHD, it's the thousandth (BHD has three decimal places).
So $12.34 USD is stored as 1234n (BigInt).
Why not floats?
The famous example: 0.1 + 0.2 in JavaScript is 0.30000000000000004,
not 0.3. That's not a JavaScript bug — it's how IEEE 754 floating-
point works in every language. Floats are wrong for money.
A bookkeeping error of 1 cent compounded over thousands of transactions becomes an audit nightmare. Money math has to be exact.
Why not Number integers?
JavaScript's Number can safely hold integers up to 2⁵³ - 1, which
is about $90 trillion when in cents. Plenty for most. But:
- "Most" isn't "all" — some currencies have more decimal places.
- Strict accounting demands exactness regardless of magnitude.
- The cost of using BigInt is negligible — modern engines handle it fast.
Why not Decimal (BCD)?
Decimal libraries (decimal.js, Big.js) work — they were a common
choice before BigInt was widely available. But:
- They're external dependencies. BigInt is built into V8 + Node + every modern runtime.
- They're slower at scale.
- They invite "what's the right precision?" arguments. With minor units there's no precision question — it's an integer.
On the wire
The REST API surfaces amounts as decimal strings of minor units
("1234" for $12.34). Strings because JSON can't represent BigInts
natively, and strings preserve precision on all clients.
Wrap them in your language's BigInt-equivalent on receive:
// Node / browser
const cents = BigInt(response.data.lines[0].debit);# Python — int is already arbitrary precision
cents = int(response['data']['lines'][0]['debit'])In the database
Postgres BigInt columns. journal_line.debit and journal_line.credit
are both bigint. Indexes work normally.
In the UI
The form lets you type "12.34" or "1234" or 1200.00. The server
parses with the org's currency and stores 1234n. On display, we
format minor units back with the currency's exponent — 1234n USD →
"$12.34".
Why this matters for accounting kernels
Pacioli's system has to be exact. If the math drifts, debits ≠ credits, and the entire correctness guarantee evaporates. BigInt minor units is the modern, simple way to honor what double-entry has always demanded.