← Back to news

Fintech Engineering Handbook

w.pitula.me|335 points|112 comments|by signa11|Jun 27, 2026

Fintech Engineering Handbook

Author: Voytek Pitula
Last Updated: June 27, 2026

Welcome to the Fintech Engineering Handbook. This guide is designed to outline the essential architectural patterns required when building software where the primary objective is the movement and management of money.

Depending on your needs, you can read this as a comprehensive manual or jump to specific sections to solve an immediate technical hurdle.

Goals of this Handbook

  • Onboarding: Help engineers understand the domain and the patterns that ensure financial systems remain trustworthy.
  • Reference: Provide a shared technical vocabulary and a go-to resource for common problems.
  • Education: Explain the fundamental differences between "standard" software engineering and engineering for money.

[!IMPORTANT] This is a living document. Contributions and updates are encouraged to keep the patterns current.


Core Principles

Every pattern described in this handbook serves one of these three foundational pillars:

  1. No Invented Data: Money cannot be created from nothing. We must prevent duplicates or arbitrary balance adjustments.
    • Enforcement: Use idempotency, deduplication, and reconciliation.
  2. Total Traceability: Every single movement of money must be recorded and persisted.
    • Enforcement: Use full precision, at-least-once delivery, event sourcing, audit trails, and immutability.
  3. Zero Trust: Do not trust external APIs, internal microservices, or the general state of the world.
    • Enforcement: Verify all webhooks, cross-reference data across multiple sources, and ensure the system fails loudly when assumptions are violated.

Representing Money

Before money can be transferred or logged, it must be modeled. Decisions made at this layer are critical; any error here propagates through every subsequent layer of the application.

Precision Handling

Choosing how to represent monetary values is a foundational decision.

MethodProsConsBest Use Case
Floating PointFast, memory efficientUnpredictable precision lossNever use for money
BigDecimalPrecise control, predictable roundingSlower, requires specific librariesIntermediate FX or pricing math
IntegersFast, no precision loss, simpleRequires tracking the "smallest unit"Final storage of fiat/crypto

The Integer Approach

For most fiat currencies, it is best to store values as integers in the smallest possible unit. For example, €12.34 is stored as 1234.

  • Standard: Refer to ISO 4217 for the number of decimals (do not assume it is always 2).
  • Crypto: Uses the same logic (e.g., satoshis for BTC, wei for ETH). However, crypto has two unique challenges:
    1. Precision is defined by the token (e.g., an ERC-20 token might have 18 decimals).
    2. Values often exceed 64-bit integer limits, requiring arbitrary-width integers.

Hybrid Strategies

Storage and computation are separate decisions. A common pattern is: Integer Storage \rightarrow BigDecimal for Calculation \rightarrow Integer Storage

Serialization and Data Transfer

When sending money over the wire (e.g., via JSON), avoid using raw numbers. Most JSON parsers treat numbers as IEEE-754 doubles, which reintroduces the floating-point problem.

Correct ways to serialize money:

  • As a string: "12.34"
  • As an integer in the smallest unit: 1234
{
  "transaction_id": "tx_123",
  "amount": "1234", 
  "currency": "EUR",
  "precision": 2
}

The Art of Rounding

Rounding must be explicit. It should occur during division, currency conversion, fee application, or when shifting between precisions.

  • Conservative (Round Down): Used to ensure you don't spend money you don't have.
  • Statistical (Half-Even): Used to minimize cumulative bias over many transactions.

Warning: Rounding can lead to the "sum of parts" problem. If a total is split and each part is rounded, the sum of those parts may not equal the original total: rounded_partsoriginal_total\sum \text{rounded\_parts} \neq \text{original\_total} This often requires explicit handling (e.g., assigning the remaining penny to the last recipient).


Currency Handling

Money is not just a number; it is a pair of (Value, Currency).

Implementation Best Practices

  • Use a Money newtype (a dedicated struct or class) to prevent mixing values.
  • Prohibit the addition of two different currencies (e.g., USD + EUR should throw an error).
  • Ensure conversions are explicit and use a strictly controlled exchange rate.
  • Validate all currency codes at the system boundary.

Fiat vs. Crypto Identifiers

While fiat currencies use unique codes (USD, GBP), cryptocurrencies require more detail:

  • Fiat: CurrencyCode
  • Crypto: (Network, ContractAddress)

Note: Pegged, wrapped, or bridged assets are not identical to the underlying asset. Treating them as interchangeable effectively "creates value" out of thin air, violating our core principles.


FX Rates

Foreign Exchange (FX) rates facilitate the conversion between currencies.

Key Nuances

  1. Non-Invertibility: The rate for EUR/USD is not simply the inverse of USD/EUR.
  2. The Spread: In real markets, there is a bid/ask spread (the difference between the buying and selling price).

FX Spread Concept

Rate Types

  • Current-time Rate: Used for real-time valuation of holdings. This is typically not stored but derived from the result and original amounts.
  • Stored Rate: A specific rate locked in at the time of a transaction for audit purposes.