Fintech Engineering Patterns: The Handbook Every SaaS Builder Needs Before Touching Money

Money bugs don't get filed in Jira. They get filed with regulators.
That's the gravitational difference separating fintech engineering from every other software domain. Miscalculate a UI animation and users shrug. Miscalculate a balance — even by a single cent — and you're dealing with audits, chargebacks, potential AML violations, and customers who want to know exactly where their money went. They are right to ask.
Jacek Piłat's Fintech Engineering Handbook is the clearest articulation of fintech engineering patterns that prevent those incidents. It's not a vendor pitch or a framework README. It's a publicly maintained engineering resource that reads like something written by someone who has personally felt the consequences of getting these things wrong — because the patterns are too specific to be theoretical.
If your SaaS touches payments, subscriptions, wallets, crypto, or any flow where numbers represent real money, this is the technical foundation worth understanding before you ship.
Three Invariants That Cannot Break
Every pattern in the handbook traces back to three properties treated as non-negotiable:
- No invented data — Money cannot be created out of nowhere. No duplicates, no unauthorized balance updates. Every cent that appears must be traceable to a source.
- No lost data — Every movement of money must be persisted with full precision, at-least-once delivery, and an immutable audit trail.
- No trust — Verify external providers, internal components, and your own assumptions. Design for failure at every integration boundary.
These aren't aspirational guidelines. They're architectural constraints that shape every decision downstream. The handbook is explicit: "Money can't be created out of nowhere, so we can't tolerate duplicates or arbitrary balance updates." If your SaaS system design doesn't enforce all three, you don't have a fintech system — you have a time bomb with a payment integration attached.
The Money Representation Problem Most Builders Skip
Before you can move money, you have to represent it correctly. This is where most SaaS builders first go wrong.
Floating point is disqualified. The canonical example: 0.1 + 0.2 in most languages returns 0.30000000000000004. That error, applied at scale across millions of transactions, becomes real money that either appears or disappears. JSON compounds this problem — the spec doesn't mandate more than IEEE-754 double precision, meaning a bare number like 12345678901234.56 silently loses precision in most parsers.
The handbook's four approaches, ranked by use case:
| Approach | Best For | Risk |
|---|---|---|
| Minor-units integer | Fiat currencies (EUR 12.34 → 1234 cents) | Must track ISO 4217 precision per currency |
| Arbitrary precision (BigDecimal) | FX calculations, intermediate math | Slower; rounding must be explicit |
| Rational numbers | Maximum precision guarantee | Requires custom types; format conversion loses precision |
| Floating point | Nothing in fintech | Unpredictable rounding at scale |
The serialization rule: always write money as a string ("12.34") or an integer in smallest units. Never a bare JSON number.
Currency is the other half of the equation. Money is never just a number — it's an amount paired with a currency, always. The handbook's position: pack them together in a Money struct and prohibit cross-currency arithmetic entirely. EUR + USD is a type error waiting to corrupt a ledger. Every conversion requires explicit rates, explicit timestamps, and an explicit business decision about which rate applies.
Balance Is Never Stored
This is the concept that most clearly separates fintech engineering from general backend work: balance is derived, never stored.
Double-entry bookkeeping — the accounting foundation the handbook builds on — means every money movement creates paired journal entries. A deposit debits an external account and credits your platform account. A withdrawal reverses that. Balance is always SUM(credits) - SUM(debits) computed over the movement history.
Why does this matter for SaaS system design? Because stored balance fields are lies waiting to happen. A race condition between concurrent operations, a crash mid-update, a reconciliation bug — any of these creates a stored balance that diverges from reality. When balance is derived from an append-only ledger of movements, there's no balance field to corrupt.
Every ledger entry also needs three distinct timestamps, not one:
- Value time: when the transaction actually occurred
- Booking time: when it was recorded in the system
- Settlement time: when money physically transferred (T+2 for most ACH = 2 business days after value date)
These diverge constantly. ACH payments have today's value date but settlement two days out. Backdated corrections have a booking time after the value time. Collapsing all three into a single created_at timestamp is how fintech products fail regulatory reporting requirements — a detail that only surfaces during audits, when fixing it is expensive.
Idempotency in APIs: The Non-Negotiable
If fintech engineers cite one pattern above all others, it's idempotency. The handbook's treatment is the most practical I've encountered.
The setup: distributed systems cannot guarantee exactly-once delivery. Networks drop. Services restart mid-request. Clients time out and retry. You will receive the same request twice. The question is whether your system handles it correctly.
Idempotency in APIs works through idempotency keys — client-generated UUIDs attached to every state-changing request. When your service receives a request with a key it's already processed, it returns the original result without re-executing the operation. No duplicate charge. No double credit. The client can retry safely.
What the handbook adds beyond the basics:
Concurrent duplicates are the hard case. Two identical requests arriving simultaneously must be deduplicated atomically. A database unique constraint on the idempotency key column, combined with appropriate isolation, is the only reliable approach. Application-level "check then insert" with any gap between them fails under concurrent load — the classic TOCTOU race.
Time-window deduplication is a trap. "We only deduplicate for 24 hours" sounds operationally reasonable. It's a correctness compromise. If a retry arrives on day two, you've invented a duplicate. The only safe window is permanent, or as close to permanent as your storage budget allows.
Every step in a flow must be idempotent. Not just the API entry point — every operation in a multi-step money flow must be re-executable from any point. This is what makes resumability possible. When a service crashes mid-flow, the recovery process replays from where it left off. If step three isn't idempotent, the replay creates a duplicate effect.
The same principle applies to outbound calls. When you call a payment provider and the response times out, you don't know if the charge happened. Your retry must pass your idempotency key to the provider and check for existing results before resubmitting.
Event-Driven Architecture: The Outbox Pattern and Why It Matters
Fintech systems are naturally event-driven: payment authorized → compliance check triggered → ledger posted → notification sent. Event-driven architecture is how you keep these steps decoupled, auditable, and survivable across failures.
The problem: you cannot atomically write to a database and publish to a message queue. The two operations are on different systems. If you write the database state and crash before publishing, downstream consumers never hear about it. If you publish first and crash before the database write, you've broadcast an event for state that doesn't exist.
The handbook's solution: the outbox pattern. Write the event to a dedicated table in the same database transaction as the state change. A separate, independent process reads from that outbox table and publishes reliably, retrying until success. The database write is atomic with the state change; publishing can fail and recover without losing the event.
Combined with consumer-side deduplication on a stable event ID, this gives you at-least-once delivery with exactly-once effect — the closest distributed systems get to reliable.
The alternative is Change Data Capture: tools like Debezium tail the database write-ahead log and emit events automatically, without requiring an outbox table. Operationally heavier, but transparent to application code.
Both share the same consumer contract: deduplicate on event ID. At-least-once delivery means events will repeat. Idempotent consumers make that harmless.
The handbook also covers webhooks from the other direction — receiving events from external providers like payment processors. Its framing is worth internalizing: "Don't trust the webhook. Treat it as a hint that something happened, not a trustworthy account of what happened." Webhooks arrive out of order, arrive late, arrive stale, and sometimes don't arrive at all. The correct pattern: acknowledge fast (return 2xx after durable storage), then query the provider's API for authoritative state before acting on what the webhook claimed.
List Your Fintech Tool on SaaSCity
Building a fintech infrastructure product? Shipping a payment SDK, ledger service, compliance API, fraud detection tool, or reconciliation system?
SaaSCity.io is a directory for SaaS and developer tools — your listing isn't a static page. It's a building in an interactive 3D digital city, visible to developers and founders actively evaluating infrastructure for their fintech stack.
- Free to list: Submit in under 2 minutes — no credit card, no catch.
- Earn dofollow backlinks: Every listing builds domain authority that compounds over time.
- 3D city map visibility: Your product appears in the SaaSCity engine — the most distinctive developer tool directory in the space.
- Reach builders, not browsers: Our audience is engineers and founders making real purchasing decisions.
Funds Reservation and the Balance Check That's Probably Wrong
There's a race condition in most SaaS billing systems that only surfaces at scale. The handbook calls it the funds reservation problem.
The scenario: a user has $100 and simultaneously initiates two $70 purchases. Without reservation, both read the balance as $100, both pass the check, both charges proceed, and the balance settles at -$40. Prohibited but not impossible — the classic "forbidden ≠ unrepresentable" failure.
Funds reservation fixes this by introducing two balance concepts:
- Total balance: all funds, including reserved
- Available balance: total minus currently reserved
Every check and new reservation runs against available balance. When a reservation is created, available balance drops immediately. When the operation settles, the reservation closes at the actual amount and releases any remainder.
The implementation requirement that can't be skipped: the balance check and the reservation write must be atomic. Check-then-reserve with any gap between them races under concurrent load. A row-level lock or serializable transaction that makes the check and the reservation a single operation is what prevents the race condition from becoming a real money problem.
What SaaS Builders Should Actually Do
The handbook isn't written for pure-play fintech startups. It's for anyone whose SaaS has a payments or money-movement component — which, in 2026, is most products that retain users long-term.
Add idempotency keys to every state-changing endpoint before you need them. Retrofitting idempotency into a live payment API is significantly harder than building it in from the start. The blast radius of a missing idempotency key is a duplicate charge; the blast radius of a duplicate charge is a support ticket, a chargeback, and a user who doesn't come back. The same principle behind why harness engineering teams build verification infrastructure before scale applies here — correctness tooling built early is orders of magnitude cheaper than incident response.
Never store derived state directly. If a value can be computed from your ledger, derive it. Balance, total spend, lifetime revenue — all computed from movements, never persisted as a writable field. Stored values drift; computed values don't. This also means your audit trail remains the single source of truth, which is what regulators and your future self will want.
Test through retries, not around them. The handbook's generative idempotency testing recommendation is one of the most practical pieces of engineering advice in the document: write test middleware that automatically retries every operation and asserts that the second call produces identical results with no additional side effects. If that test passes, your system is safe on unreliable networks. If it doesn't, you know where the gaps are before a production incident reveals them. Engineers using AI coding tools to build financial systems should double-check this — clear context and explicit constraints around idempotency are the difference between generated code that's correct and code that looks correct until it's charged someone twice.
Store every external API request and response. Verbatim. Structured and queryable. When a payment provider dispute arises six months from now, the raw request/response log is the only evidence you have of what actually happened. The handbook is explicit: this isn't optional logging hygiene. It's the audit trail foundation.
The Line That Closes It
The handbook opens with a phrase that becomes a lens for everything else: "An audit trail that can be edited proves nothing."
That sentence implies a second one: every engineering shortcut in a money system is a correctness debt that eventually becomes an incident report.
The patterns in the handbook aren't clever tricks. They're the minimum viable engineering discipline for systems where correctness isn't a quality attribute — it's a legal requirement. Idempotency in APIs, double-entry ledgers, event-driven architecture with reliable delivery, funds reservation with atomic checks: none of these are complex. All of them are load-bearing.
Read the handbook. Then audit your payment integration against it. The gaps will be obvious. Fix them before production shows you where they are.
SaaSCity.io covers fintech infrastructure and developer tools for SaaS builders. Explore the SaaSCity directory to discover what's shipping right now — or list your own product.
Get your SaaS in front of founders
List your product on the SaaSCity live city map — a permanent listing, real discovery, and a backlink from a high-DR directory. Free to start; upgrade for a dofollow link and a building on the map.


