Engineering principles for building financial systems

Money representation & rounding

  • Strong focus on avoiding binary floating point for money.
  • Two camps:
    • Use integers as fixed-point units (cents, micros, “1/10,000 of a cent”, crypto-style 128–256-bit ints). Rounding only at system boundaries / UI.
    • Use decimal types (BigDecimal, Decimal) where available; these handle precision and rounding modes natively and map better to domain concepts.
  • Several warn that JavaScript’s Number type is unsafe for regulatory-grade money logic; BigInt or backend-only decimal/int logic is preferred.
  • Some argue arbitrary precision rationals/decimals are fast enough for “normal” accounting, but too slow for high-volume trading.
  • Rounding rules themselves should be explicit, testable domain objects, often country / product specific, with regulators sometimes imposing precision rules.

Time, time zones, and leap seconds

  • Debate over “just use integer timestamps”:
    • Works for past events and controlled offsets (e.g., “48 hours from now”).
    • Fails for future calendar-dependent events (cutoffs, tax year ends, holidays, DST moves, leap seconds, changing time-zone law).
  • Suggested patterns: store UTC plus original timezone (or full zone, not just offset), and sometimes distinguish “observed timestamp” from “future scheduled time”.
  • Leap seconds: most financial systems ignore them, but some markets and regulators have explicitly prepared for leap-second events.

Accounting system semantics: accuracy, consistency, completeness

  • Several argue “consistency” is as important as accuracy.
  • Real systems accept late and out-of-order events; multiple time dimensions (trade requested, filled, booked, settled, etc.) and multiple layered ledgers are standard.
  • Systems must represent temporarily “wrong” or inconsistent states to reconcile later.
  • Materiality is seen as a reporting/audit concept, not a system-design justification; internal records should be exact, even if reports aggregate.

Currency conversion & FX

  • Strong view that systems should not convert currencies “for convenience”; amounts are legally in specific currencies.
  • Conversion should occur only at defined business events (e.g., invoice issue, funds transfer), with explicit FX rates and gains/losses lines.
  • Internal dashboards may use approximate FX averages, but that’s BI, not core accounting.

Identifiers and events

  • Transactions often have many external IDs (per counterparty/system) and multiple timestamps.
  • Recommended: model IDs as one-to-many relations with metadata (issuer, type, validity window) rather than assuming a single canonical ID.

Databases, ACID, and architecture

  • Many advocate using relational databases with decimal types, ACID guarantees, and SQL-based reporting for bookkeeping-scale systems.
  • Others warn that treating an ACID DB as the sole “source of truth” can clash with ledger/event-based accounting, where compensating actions, not rollbacks, are correct.
  • Distinction emphasized between fast trading models vs slower, robust bookkeeping stores.

Batch vs streaming

  • Disagreement with “batch is just a special case of streaming”.
  • Always-on streaming and periodic batch runs have different reliability, performance, and migration constraints, especially when large historical datasets and external APIs are involved.

UI/UX for accounting software

  • Multiple accountants/users complain that mainstream accounting UIs are far worse than paper or spreadsheets.
  • Users frequently export to spreadsheets despite custom UIs.
  • Desire for interfaces that surface double-entry structure more transparently and match real workflows.

Testing and auditability

  • Heavy testing is considered crucial, but tests themselves become audit artifacts.
  • Refactors may require a “write-then-solve” approach to keep tests and historical expectations explainable to auditors.