Banking System Database Schema database schema
The Banking System Database Schema database schema is a DB Planner template with 34 tables, 305 columns and 75 relationships, free to use. Core tables include account_holders, account_products, account_restrictions, accounts. It can be opened as an interactive diagram or exported as PostgreSQL, MySQL, or MSSQL DDL.
- Tables
- 34
- Columns
- 305
- Relationships
- 75
- Category
- Fintech
- Exports
- DBML, SQL, C#
- Price
- Free
What this schema models
A core banking database schema built the way banks actually build them: on a double-entry ledger. 34 tables and 33 enums covering customers and KYC, branches and staff, multi-currency accounts, the ledger itself, payments and mandates, cards and authorisations, lending with amortisation schedules, fees, statements, disputes and a write-once audit trail. THE RULE EVERYTHING ELSE FOLLOWS FROM Money moves as DOUBLE ENTRY. A transaction is only a header — it deliberately has no amount column, because a single transaction can span currencies. The actual movement lives in ledger_entries, two or more rows whose signed amounts sum to exactly ZERO. accounts.balance_minor is a cached running total that can always be rebuilt by summing entries. There is no UPDATE anywhere that moves money, only inserts. This matters because a bank that stores balance as the truth and transactions as a log cannot answer "why is this figure wrong" — and that question is the entire job. Reversal is a new, opposite transaction referencing the original. Nothing is ever deleted. SUPPORTING DECISIONS - Amounts are integers in MINOR UNITS, always beside an explicit currency. Rates are basis points. No floats anywhere. - currencies carries minor_unit_digits, because JPY has 0, USD has 2 and KWD has 3. Hard-coding a divisor of 100 is a bug waiting to happen. - Available balance is balance minus active holds, computed rather than stored. A card authorisation places a hold and reduces available funds without touching the ledger; capture releases the hold and posts a real transaction. That gap is precisely why available and current balance differ. - account_holders is many-to-many, so joint accounts have two primary holders and a signatory can transact without owning the balance. - Account restrictions and freezes are rows with a lifted_at, not booleans on accounts, so the history survives. - Customer address history is versioned with valid_from and valid_to. Regulators ask where somebody lived at a point in time. - Loans copy interest_rate_bps at approval; repricing the product later cannot rewrite an existing loan. The amortisation schedule is generated at disbursement and frozen, and comparing it against payments is what defines arrears. - Every loan payment records its own allocation across principal, interest and fees, so the split is never recomputed retroactively. - Interest accrues daily and posts monthly, and keeping the daily rows is what makes a mid-month closure calculable. - Statement opening and closing balances are frozen at generation, so a reissued statement for a past period shows the same figures forever. - Dispute provisional credit is a real transaction, reversed if the dispute fails — never a temporary balance adjustment. - audit_logs is append-only and write-once, capturing before and after values. It is the table an auditor actually asks for. WHAT YOU GET Clean DBML that imports straight into DB Planner, plus a laid-out board with cards colour-coded by zone — customers, bank reference, accounts, ledger, payments, cards, lending, fees and statements, disputes and audit — with sticky notes explaining each decision and every table carrying its own Note. Postgres-flavoured types that port cleanly to MySQL, Oracle or SQL Server. Useful for developers building core banking, neobank or fintech ledger infrastructure, students who need a realistic banking ER diagram for a DBMS project, and teams designing money movement who want to see double-entry modelled properly before writing their first migration. This is a schema design reference, not a certified banking system — validate against your own regulatory and accounting requirements before production use.
Tables (34)
| Table | Columns |
|---|---|
| account_holders | 5 |
| account_products | 10 |
| account_restrictions | 7 |
| accounts | 10 |
| alerts | 8 |
| audit_logs | 10 |
| beneficiaries | 10 |
| branches | 7 |
| card_authorizations | 11 |
| cards | 12 |
| currencies | 4 |
| customer_addresses | 11 |
| customers | 14 |
| direct_debits | 8 |
| dispute_evidence | 6 |
| disputes | 12 |
| employees | 7 |
| exchange_rates | 6 |
| external_banks | 5 |
| fee_charges | 9 |
| fee_schedules | 8 |
| holds | 10 |
| interest_accruals | 7 |
| kyc_documents | 11 |
| ledger_entries | 10 |
| loan_payments | 9 |
| loan_products | 10 |
| loan_schedule_entries | 8 |
| loans | 14 |
| standing_orders | 9 |
| statements | 10 |
| transaction_categories | 4 |
| transactions | 11 |
| transfers | 12 |
Relationships (75)
account_holders.account_id references accounts.idmany to oneaccount_holders.customer_id references customers.idmany to oneaccount_products.currency references currencies.codemany to oneaccount_restrictions.account_id references accounts.idmany to oneaccount_restrictions.placed_by references employees.idmany to oneaccounts.branch_id references branches.idmany to oneaccounts.currency references currencies.codemany to oneaccounts.product_id references account_products.idmany to onealerts.account_id references accounts.idmany to onealerts.customer_id references customers.idmany to oneaudit_logs.actor_customer_id references customers.idmany to oneaudit_logs.actor_employee_id references employees.idmany to onebeneficiaries.currency references currencies.codemany to onebeneficiaries.customer_id references customers.idmany to onebeneficiaries.external_bank_id references external_banks.idmany to onecard_authorizations.card_id references cards.idmany to onecard_authorizations.currency references currencies.codemany to onecard_authorizations.hold_id references holds.idmany to onecard_authorizations.transaction_id references transactions.idmany to onecards.account_id references accounts.idmany to onecards.customer_id references customers.idmany to onecustomer_addresses.customer_id references customers.idmany to onedirect_debits.account_id references accounts.idmany to onedispute_evidence.dispute_id references disputes.idmany to onedispute_evidence.submitted_by references employees.idmany to onedisputes.card_authorization_id references card_authorizations.idmany to onedisputes.currency references currencies.codemany to onedisputes.customer_id references customers.idmany to onedisputes.provisional_credit_transaction_id references transactions.idmany to onedisputes.transaction_id references transactions.idmany to oneemployees.branch_id references branches.idmany to oneexchange_rates.base_currency references currencies.codemany to oneexchange_rates.quote_currency references currencies.codemany to onefee_charges.account_id references accounts.idmany to onefee_charges.currency references currencies.codemany to onefee_charges.fee_schedule_id references fee_schedules.idmany to onefee_charges.transaction_id references transactions.idmany to onefee_charges.waived_by references employees.idmany to onefee_schedules.currency references currencies.codemany to onefee_schedules.product_id references account_products.idmany to oneholds.account_id references accounts.idmany to oneholds.currency references currencies.codemany to oneholds.settled_transaction_id references transactions.idmany to oneinterest_accruals.account_id references accounts.idmany to oneinterest_accruals.currency references currencies.codemany to oneinterest_accruals.loan_id references loans.idmany to oneinterest_accruals.posted_transaction_id references transactions.idmany to onekyc_documents.customer_id references customers.idmany to onekyc_documents.verified_by references employees.idmany to oneledger_entries.account_id references accounts.idmany to oneledger_entries.category_id references transaction_categories.idmany to oneledger_entries.currency references currencies.codemany to oneledger_entries.transaction_id references transactions.idmany to oneloan_payments.loan_id references loans.idmany to oneloan_payments.schedule_entry_id references loan_schedule_entries.idmany to oneloan_payments.transaction_id references transactions.idmany to oneloan_products.currency references currencies.codemany to oneloan_schedule_entries.loan_id references loans.idmany to oneloans.approved_by references employees.idmany to oneloans.customer_id references customers.idmany to oneloans.disbursement_account_id references accounts.idmany to oneloans.product_id references loan_products.idmany to onestanding_orders.beneficiary_id references beneficiaries.idmany to onestanding_orders.currency references currencies.codemany to onestanding_orders.from_account_id references accounts.idmany to onestatements.account_id references accounts.idmany to onestatements.currency references currencies.codemany to onetransaction_categories.parent_id references transaction_categories.idmany to onetransactions.initiated_by references customers.idmany to onetransactions.reverses_transaction_id references transactions.idmany to onetransfers.beneficiary_id references beneficiaries.idmany to onetransfers.currency references currencies.codemany to onetransfers.from_account_id references accounts.idmany to onetransfers.to_account_id references accounts.idmany to onetransfers.transaction_id references transactions.idmany to one
How to use this template
- Open the diagram to see the tables and how they relate.
- Copy it into your workspace. You get your own editable copy.
- Export it as PostgreSQL, MySQL, or MSSQL DDL, or as C# models.
Frequently asked questions
- What is in the Banking System Database Schema schema?
- 34 tables and 75 relationships, across 305 columns. The table names and the full relationship list are shown on this page.
- Can I export it to PostgreSQL or MySQL?
- Yes. Every DB Planner template exports as DBML, PostgreSQL, MySQL, or MSSQL DDL, and as C# models.
- Is this template free?
- Yes. You can open it in the browser without an account, and copy it into your own workspace with a free DB Planner account.
- Can I change it after copying it?
- Yes. A copy is yours: you can rename tables, add columns, and export it. Changes the author makes later do not affect your copy.