DiagramDB / Banking System ERD

ER Diagram for Banking System

Customers hold accounts at branches (some accounts are joint), money moves through transactions, and customers take out loans. The joint-account rule is what turns a simple one-to-many into a junction table.

All examples
Drawing 7 tables…

Why each relationship is drawn this way

  • accounts ↔ customersJoint accounts mean one account can have several holders and one customer several accounts: account_holders resolves the many-to-many.
  • account → transactionsEvery transaction posts to one account. Transfers also record the counterparty account (nullable for cash deposits).
  • branch → accounts / loansEach account and loan is managed by one branch.
  • loan → loan_paymentsRepayments are rows, not a running column, so the payment history is never lost.

The schema

CREATE TABLE branches (
  id INT PRIMARY KEY,
  name VARCHAR(80) NOT NULL,
  city VARCHAR(80) NOT NULL
);
CREATE TABLE customers (
  id INT PRIMARY KEY,
  full_name VARCHAR(120) NOT NULL,
  date_of_birth DATE NOT NULL,
  email VARCHAR(255) UNIQUE,
  phone VARCHAR(30)
);
CREATE TABLE accounts (
  id INT PRIMARY KEY,
  branch_id INT NOT NULL REFERENCES branches(id),
  account_number VARCHAR(34) NOT NULL UNIQUE,
  type VARCHAR(20) NOT NULL,
  balance_cents BIGINT NOT NULL DEFAULT 0,
  opened_on DATE NOT NULL
);
CREATE TABLE account_holders (
  account_id INT NOT NULL,
  customer_id INT NOT NULL,
  PRIMARY KEY (account_id, customer_id),
  FOREIGN KEY (account_id) REFERENCES accounts(id),
  FOREIGN KEY (customer_id) REFERENCES customers(id)
);
CREATE TABLE transactions (
  id BIGINT PRIMARY KEY,
  account_id INT NOT NULL REFERENCES accounts(id),
  amount_cents BIGINT NOT NULL,
  kind VARCHAR(20) NOT NULL,
  created_at TIMESTAMP NOT NULL,
  counterparty_account_id INT REFERENCES accounts(id)
);
CREATE TABLE loans (
  id INT PRIMARY KEY,
  customer_id INT NOT NULL REFERENCES customers(id),
  branch_id INT NOT NULL REFERENCES branches(id),
  principal_cents BIGINT NOT NULL,
  annual_rate DECIMAL(5,3) NOT NULL,
  starts_on DATE NOT NULL,
  term_months INT NOT NULL
);
CREATE TABLE loan_payments (
  id INT PRIMARY KEY,
  loan_id INT NOT NULL REFERENCES loans(id),
  paid_on DATE NOT NULL,
  amount_cents BIGINT NOT NULL
);

Design notes

  • Use a signed amount (positive credit, negative debit) and derive the balance from transactions, or keep balance_cents in sync inside the same database transaction.
  • BIGINT cents comfortably holds any realistic balance.

Tables at a glance

  • branches: id, name, city
  • customers: id, full_name, date_of_birth, email, phone
  • accounts: id, branch_id, account_number, type, balance_cents, opened_on
  • account_holders: account_id, customer_id
  • transactions: id, account_id, amount_cents, kind, created_at, counterparty_account_id
  • loans: id, customer_id, branch_id, principal_cents, annual_rate, starts_on, term_months
  • loan_payments: id, loan_id, paid_on, amount_cents

Questions

What are the entities in a banking system ER diagram?

This design uses 7 tables: branches, customers, accounts, account_holders, transactions, loans, loan_payments. Joint accounts mean one account can have several holders and one customer several accounts: account_holders resolves the many-to-many.

How many relationships does the banking system ER diagram have?

8 foreign-key relationships. The many-to-many ones are resolved with junction tables, which is how they must be stored in a relational database.

Can I edit this ER diagram and export it?

Yes. “Edit in the ER diagram generator” opens the same SQL in the editor, where you can add tables, drag boxes and export SVG, PNG, Mermaid, DBML or SQL for PostgreSQL, MySQL, SQL Server or SQLite.

Which notation is used?

Crow’s foot: a fork means many, a bar means exactly one and a circle means optional (zero). A nullable foreign key gets the circle on the parent end.

More ER diagram examples