Part 10 · FinTech engineering
Ledgers and core bankingالسجلات والأنظمة الأساسية Core banking
Never store a balance. Store every movement, and add them up to get the balance. This is the single most important rule in financial engineering.
5 minute read
A ledger is a list of every movement in and out, in the order it happened. A balance is not a number stored in a field. It is the sum of those movements. The core system is the software that holds that ledger.
The truth in a money system is the list of movements that produced its current state.
Why not keep the balance in a column and add and subtract?
This is the first thing any engineer thinks of, and it is entirely sensible in most software. A balance column updated on every transaction looks simpler and faster.
It is a mistake that destroys financial systems, because it loses the history.
Imagine a customer's balance reads 470 riyals and they say it should be 520. What do you do? You have one number that tells you nothing about where it came from. You cannot tell whether something was deducted twice, or a payment was never posted, or the error happened two months ago.
Store the movements instead of the balance and the balance becomes a result you calculate rather than a number you keep. You read the lines one by one and find the duplicate debit with its date, its identifier and its source.
That is the whole idea of a ledger: the truth is the list of what happened, not the last number displayed.
Something follows that surprises people arriving from outside: errors are not deleted and not edited. If an amount was posted wrongly, you do not correct the old line. You add an opposite line that cancels it. The error stays visible and the correction stays visible, and an auditor two years later can see exactly what happened.
Editing a line in a financial ledger does not fix an error. It erases evidence.
Entries come before balances
An app displays one balance because customers need a quick answer. A dependable system does not treat that number as the source of truth. It sums entries for what the customer owns and what is currently spendable.
A mutable balance column is not enough. A debit may succeed while its update fails, or two requests may overwrite each other. When a difference appears, the column cannot identify its cause. Movements let you rebuild the balance after failure.
Double-entry (القيد المزدوج) records every movement on two sides. When a customer pays a merchant SAR 100, the customer account falls by 100 and merchant payables rise by 100. The two sides sum to zero.
Loading diagram…
Zero is a test
Zero does not mean money disappeared. It means every value leaving one place entered another. The other side may be company fees, settlement in transit, or a liability to a customer. A missing counterpart exposes an incomplete movement.
An unbalanced entry is a bug. Do not hide the difference in a suspense account or round it away. A tiny error may repeat a million times.
Make the database reject unbalanced transactions. Save both sides atomically so the debit cannot exist without the credit. Balance each currency separately because a riyal and dollar do not cancel each other.
Use the smallest unit
Store money as integer smallest units. Represent SAR 10.25 as 1025 halalas. Floating-point numbers cannot represent some fractions exactly and can produce values such as 0.3000000004.
Always store currency with value. 1000 may mean ten riyals or one thousand yen. Never combine currencies in one balance. Foreign exchange needs entries for each currency plus the rate, time, and source.
Define rounding at explicit boundaries. A fee calculation may produce part of a halala. The system must know how it rounds and who receives the remainder. Separate services must not invent separate rules.
Never edit history
An immutable (غير قابل للتعديل) entry does not change after posting. If the company sends SAR 50 instead of SAR 5, an operator does not edit the row. They add a reversing 50 entry and then the correct 5 entry.
This preserves what happened, who corrected it, and when. Support can explain two balance changes. Engineers can reproduce an account at any earlier time.
Restrict writing to a dedicated service, record the actor, reason, and request identifier, and block deletion from ordinary administration tools.
Separate financial states
A customer may have a ledger balance of SAR 1,000 but only SAR 800 available. A hotel may be holding 200 without final settlement. Keep ledger, available, pending, and reserved amounts distinct.
Do not post a reversible authorisation as a final payment. Represent the temporary commitment. On settlement, release the hold and post the final movement. On expiry, restore availability without inventing income or loss.
Define valid state transitions. A failed payment cannot jump straight to settled, and settlement cannot occur twice. This protects the ledger from late events.
Reconcile the outside world
Reconciliation (المطابقة) compares your ledger with an external source such as a bank statement or card-network file. Your ledger may expect SAR 100,000 while the bank deposits 99,000. Every difference needs an explanation in transactions, fees, and timing.
Run reconciliation automatically each day. Match by identifier, amount, currency, and date, then queue exceptions. Equal totals do not prove equal items because one overpayment can hide one missing payment.
Give aged exceptions an owner. A transfer lacking a counterpart for three days should trigger investigation. This prevents small differences becoming unexplained balances for years.
Design end to end
Give a wallet top-up one operation identifier across customer request, provider call, result, posting, and reconciliation. After a provider timeout, assume neither success nor failure. Query by identifier before retrying the debit.
Test painful cases before launch. Stop the service after provider acceptance but before posting, duplicate the notification, and delay settlement by a day. The system should return to one balanced result without editing history.
A well-designed ledger does more than accounting. It answers customers, exposes bugs, supports reconciliation, and provides an audit trail. Every later financial feature depends on that truth remaining balanced and rebuildable.
New words here
- Double-entryالقيد المزدوج
- Recording every transaction twice, where it came from and where it went, so the two sides always cancel out.
- Immutableغير قابل للتعديل
- Cannot be changed after it is written. Ledger entries are corrected by adding a reversing entry, never by editing.
- Reconciliationالمطابقة
- Comparing your ledger against an outside source of truth, like the bank statement, to prove they agree.
The short version
- Movements are the truth. Balances are calculated from them, and can always be rebuilt.
- If your ledger does not add up to zero, that is a bug. Never round it away.
- Never edit or delete an entry. Correct it with an opposite entry so the history survives.
- Store money as integers of the smallest unit. Never use floating-point decimals.
- Reconcile against the outside world daily and automatically.
Check your understanding
Answer before reading the explanation. Getting one wrong here is worth more to you than a lucky guess.
This is a learning guide built from field experience. It is not legal, regulatory or investment advice, and it does not replace qualified professional counsel. FinTech rules change quickly and vary by country, so check the primary source before you make a decision that matters.