Markdown Editor

Database Design Document Template (ERD and Physical Model)

Database design: DBMS choice, conceptual, logical and physical models, indexes, partitioning, integrity, security, backup, capacity

Architektur & SystemdesignVollständigdatabasedesignmath

Anleitung: Use for a new database or a major schema change. Start from the access patterns in section 5 and justify every index against them; record each deliberate denormalisation with its consistency mechanism. Main pitfall: a correct schema that cannot serve the top queries fast, or a document that drifts from the migration files.

Vorschau

Database Design Document: [Database or application name]

Complete design for one database: purpose, DBMS choice, conceptual, logical and physical models, keys and indexes, normalisation decisions, partitioning, transactions, integrity, security, backup and restore, retention, migrations, capacity estimates and naming conventions. Based on common industry practice for relational database design. Replace every [bracketed] value and every row marked Example. Worked examples use an order-management schema on PostgreSQL.

Document control

FieldValue
Document ID[DBD-ORDERS-001]
Database / schema[orders_db / public]
Application(s)[orders-service, reporting-etl]
Version[0.1]
Status[Draft / In review / Approved / Superseded]
Owner (data owner)[@data-owner]
Author (designer)[@dba-or-engineer]
Classification[Internal / Confidential]
Last updatedYYYY-MM-DD
Related[System design], [Data dictionary], [Security architecture]

Approvals

RoleNameDecisionDate
Application tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Database administrator[@name][Decision]YYYY-MM-DD
Data owner[@name][Decision]YYYY-MM-DD
Security / privacy[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summaryMigration
0.1YYYY-MM-DD[@name]First draftn/a
0.2YYYY-MM-DD[@name]Example: Partitioned order_event by monthV012__partition_order_event.sql
1.0YYYY-MM-DD[@name]Example: Approved for productionV015

Contents

1. Introduction

1.1 Purpose

[What the database is for. Example: "The orders database is the system of record for customer orders, order lines, payments references and shipment status for the EU storefront."]

1.2 Scope

In scopeOut of scope
Example: Orders, order lines, order status history, shipmentsProduct catalogue (owned by Catalogue DB)
Example: Customer reference (ID and display name only)Customer personal data (owned by Customer DB)
[Item][Item]

1.3 Assumptions and constraints

  • [Example: Single region primary in eu-west-1 with a synchronous standby in another availability zone.]
  • [Example: Personal data must stay in the EU.]
  • [Example: Reporting reads go to a read replica, never the primary.]

2. DBMS selection

CriterionWeight[PostgreSQL 17][MySQL 8.4][Document store]
Relational integrity and transactionsHighStrongStrongLimited across documents
JSON support for flexible attributesMediumStrong (jsonb, GIN indexes)GoodNative
Native partitioningMediumDeclarativeYesSharding
Team skills and operations toolingHighStrongMediumWeak
Managed service availableHighYesYesYes
DecisionChosenRejectedRejected

Rationale: [Example: "Orders need multi-row transactions across order, lines and payments; PostgreSQL meets this, supports partitioning for the event table and matches the team's operational experience."]

3. Conceptual model

The main business entities and how they relate. Cardinalities reflect the business rules in section 11.

EntityBusiness meaningOwner
CustomerA person or organisation that places ordersCustomer domain
OrderA customer's request to buy products, with a delivery addressOrders domain
Order lineOne product and quantity within an orderOrders domain
PaymentA payment attempt or capture against an orderPayments domain (reference only)
ShipmentA physical delivery of some or all linesFulfilment domain (reference only)
Order eventA recorded change of order statusOrders domain

4. Logical model

The logical model adds attributes and keys. Types here are logical; the physical types are in section 6.

5. Workload and access patterns

5.1 Workload profile

CharacteristicValue
Workload typeExample: OLTP, read-heavy (reads : writes about 8 : 1)
Peak transactions per secondExample: 600
Concurrent connections (pooled)Example: 200
Largest table at 3 yearsExample: order_event, about 900 million rows

5.2 Writes

IDOperationTablesFrequency (peak)Latency target
W-01Create order with linesorders, order_line, order_event80/sp99 50 ms
W-02Change order statusorders, order_event150/sp99 20 ms
[W-nn][Operation][Tables][Rate][Target]

5.3 Reads

IDQueryFrequency (peak)Latency targetServed by index
R-01Get order with lines by order_id400/sp99 10 msPK, IX-02
R-02List a customer's orders, newest first, 25 per page120/sp99 30 msIX-01
R-03Orders in status PAID older than 2 hours (stuck orders job)1/min2 sIX-03 (partial)
R-04Status history of an order50/sp99 20 msIX-04
[R-nn][Query][Rate][Target][Index]

6. Physical design

6.1 Table orders

Holds one row per customer order. Rows are never deleted by the application; cancellation is a status.

ColumnTypeNullDefaultConstraintsDescription
order_iduuidNogen_random_uuid()PKSurrogate key
order_numbervarchar(20)NoUNIQUEHuman-readable number, ORD-2026-000123
customer_iduuidNoFK customer_refCustomer who placed the order
statusvarchar(30)No'PENDING_PAYMENT'CHECK in status listLifecycle state
currencychar(3)NoCHECK ~ '^[A-Z]{3}$'ISO 4217 code
total_amountnumeric(12,2)No0CHECK >= 0Sum of line totals
shipping_addressjsonbNoCHECK has countryCodeSnapshot at order time
created_attimestamptzNonow()Creation time (UTC)
updated_attimestamptzNonow()Maintained by trigger
versionintegerNo1Optimistic lock counter

6.2 Table order_line

ColumnTypeNullDefaultConstraintsDescription
order_line_iduuidNogen_random_uuid()PKSurrogate key
order_iduuidNoFK orders ON DELETE CASCADEParent order
line_nosmallintNoUNIQUE (order_id, line_no)Position in order
skuvarchar(40)NoProduct SKU at order time
quantityintegerNoCHECK between 1 and 999Units ordered
unit_pricenumeric(12,2)NoCHECK >= 0Price per unit at order time
line_totalnumeric(12,2)NoGenerated: quantity * unit_priceStored generated column

6.3 Table order_event

ColumnTypeNullDefaultConstraintsDescription
order_event_idbigintNoidentityPK (with occurred_at)Sequence
order_iduuidNoFK ordersOrder changed
from_statusvarchar(30)YesNull for creation
to_statusvarchar(30)NoNew status
actorvarchar(100)NoUser or service that made the change
occurred_attimestamptzNonow()Partition keyTime of change

6.4 Table [table_name]

[Repeat the column table for every remaining table, including lookup and join tables.]

7. Keys and indexes

7.1 Key strategy

DecisionChoiceRationale
Primary keysExample: UUID v7 surrogate keysGlobally unique, time-ordered so inserts stay near the right edge of the B-tree
Natural keysEnforced as UNIQUE constraints (order_number)Business lookups without coupling joins to business values
Foreign keysDeclared and indexed on the child sideIntegrity and fast parent deletes and joins

7.2 Index register

IDTableColumnsTypeUniqueServesNotes
IX-01orders(customer_id, created_at DESC)B-treeNoR-02Covers pagination by keyset
IX-02order_line(order_id)B-treeNoR-01, FK
IX-03orders(created_at) WHERE status = 'PAID'Partial B-treeNoR-03Small; only paid orders
IX-04order_event(order_id, occurred_at)B-tree, per partitionNoR-04
IX-05orders(shipping_address)GIN jsonb_path_opsNo[Support search]Review after 3 months
[IX-nn][Table][Columns][Type][Y/N][Pattern][Notes]

8. Normalisation and denormalisation

The schema targets third normal form. Deliberate exceptions:

IDDenormalised dataWhereReasonConsistency mechanism
DN-01total_amountordersAvoid summing lines on every list query (R-02)Recomputed in the same transaction as any line change; nightly reconciliation job
DN-02shipping_address snapshotordersLegal record of the address at order timeImmutable after PAID
DN-03unit_priceorder_linePrice at order time must not change with the catalogueImmutable after creation
[DN-nn][Data][Table][Reason][Mechanism]

9. Partitioning and sharding

TableStrategyKeyGranularityLifecycle
order_eventRange partitioningoccurred_atMonthlyCreated 3 months ahead by scheduled job; detached and archived after 24 months
ordersNoneRevisit above [200 million] rows
[Table][Strategy][Key][Granularity][Lifecycle]

Sharding: [Example: "Not required. A single primary handles the projected peak with 3x headroom (section 15). If needed later, shard by customer_id hash so a customer's orders stay together."]

10. Transactions, isolation and concurrency

TopicDecision
Default isolationExample: READ COMMITTED
Stronger isolationExample: SERIALIZABLE for refund creation, with retry on serialization failure (up to 3 attempts)
Optimistic lockingversion column; UPDATE ... WHERE order_id = $1 AND version = $2; zero rows updated means conflict
Pessimistic lockingSELECT ... FOR UPDATE SKIP LOCKED for the stuck-order job queue
Transaction lengthNo user think time inside a transaction; statement timeout [5 s], idle-in-transaction timeout [10 s]
Deadlock preventionLock rows in a fixed order: orders before order_line
Connection poolingExample: Transaction-mode pooler, 200 client connections onto 40 server connections

11. Data integrity rules

IDRuleEnforced byVerification
DI-01An order has at least one lineDeferred constraint triggerIntegration test
DI-02total_amount equals the sum of line_totalApplication transaction plus nightly checkReconciliation report
DI-03Status transitions follow the state machineTrigger rejects invalid from_status to to_status pairsUnit test of trigger
DI-04Currency is identical for all lines in an orderApplicationContract test
DI-05An order is never physically deletedNo DELETE grant to application rolePrivilege audit
[DI-nn][Rule][Mechanism][Check]

The order status state machine enforced by DI-03:

12. Security

12.1 Roles and privileges

RoleUsed byPrivileges
orders_ownerMigrations onlyOwns schema objects; no login outside the pipeline
orders_apporders-serviceSELECT, INSERT, UPDATE on application tables; no DELETE on orders
orders_readonlyReporting ETL, read replicaSELECT on views in schema reporting
dba_breakglassDBAs, on approved incident ticketFull access, session logged, time-limited
[Role][User][Privileges]

12.2 Data protection

ControlImplementation
Encryption in transitTLS required (sslmode=verify-full) for all clients
Encryption at restStorage encryption with customer-managed key [key alias]
Column protectionExample: Delivery phone number encrypted in the application with envelope encryption
Row-level securityExample: RLS policy on tenant_id for the multi-tenant B2B schema
MaskingNon-production copies use masked data generated by [tool]
AuditingDDL and privilege changes logged; access to dba_breakglass alerted
SecretsCredentials issued dynamically by [secrets manager], lifetime 1 hour

13. Backup, restore and retention

13.1 Backup and restore

ItemTarget or method
Recovery point objective (RPO)Example: 5 minutes
Recovery time objective (RTO)Example: 1 hour
MethodContinuous WAL archiving plus daily snapshot
Backup retention35 days point-in-time; monthly snapshot kept 12 months
Backup locationSeparate account and region, immutable storage
Restore drillQuarterly full restore to an isolated environment; time recorded
Last successful drillYYYY-MM-DD, restore time [n] minutes

13.2 Retention and archival

DataRetain in primaryThenDelete afterBasis
orders, order_line7 yearsRemain (small)10 years[Tax record-keeping requirement]
order_event24 monthsPartition detached and exported to object storage as Parquet7 years[Audit policy]
Application logs in DB30 daysDelete30 days[Policy]
[Data][Period][Action][Period][Basis]

14. Migration strategy

TopicRule
ToolExample: Versioned SQL migrations (V###__description.sql) applied by the deployment pipeline
ReviewEvery migration reviewed by a DBA or a second engineer; lock impact stated in the PR
Expand and contractAdd new structures, dual-write, backfill, switch reads, then drop old structures in a later release
Large backfillsBatched (for example 10 000 rows per batch) with throttling, outside the migration transaction
LockingCREATE INDEX CONCURRENTLY; lock_timeout set to [3 s] on DDL
RollbackEvery migration has a tested forward fix or down script; destructive steps only after one release in production
Initial data load[Source, method, validation counts]

15. Capacity and performance estimates

InputSymbolValue
Orders per daynon_oExample: 200 000
Lines per order (average)ll2.5
Status events per orderee4
Average row size, orders (with index share)sos_o1.2 KB
Average row size, order_linesls_l0.4 KB
Average row size, order_eventses_e0.25 KB
HorizonDD1 095 days (3 years)

Storage growth per day:

G=no(so+l sl+e se)=200 000×(1.2+1.0+1.0) KB≈640 MB/dayG = n_o \left(s_o + l\,s_l + e\,s_e\right) = 200\,000 \times (1.2 + 1.0 + 1.0)\ \text{KB} \approx 640\ \text{MB/day}

Size after three years, before compression and excluding archived partitions:

S=G×D≈640 MB×1 095≈700 GBS = G \times D \approx 640\ \text{MB} \times 1\,095 \approx 700\ \text{GB}

Peak write rate with a peak factor k=5k = 5:

Wpeak=k⋅no(1+l+e)86 400=5×200 000×7.586 400≈87 rows/sW_{peak} = \frac{k \cdot n_o (1 + l + e)}{86\,400} = \frac{5 \times 200\,000 \times 7.5}{86\,400} \approx 87\ \text{rows/s}
ResourceEstimateProvisionedHeadroom
Storage (3 years)~700 GB[1.5 TB with autoscaling]~2x
Peak writes~90 rows/s[Instance class][x]
Working set in memory[Hot 30 days of orders and indexes, ~25 GB][64 GB RAM]~2.5x

16. Naming conventions

ObjectConventionExample
Tablessnake_case, singular, except reserved wordsorder_line, orders
Columnssnake_case; booleans start with is_ or has_is_gift
Primary key<table>_idorder_line_id
Foreign key columnSame name as the referenced keyorder_id
Timestamps<event>_at, always timestamptzcreated_at
Indexesix_<table>__<columns>ix_orders__customer_id_created_at
Unique constraintsuq_<table>__<columns>uq_orders__order_number
Foreign key constraintsfk_<table>__<referenced>fk_order_line__orders
Check constraintsck_<table>__<rule>ck_orders__total_non_negative
Viewsv_<name>v_daily_sales

17. Appendices

17.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Do we need tenant_id now for the B2B launch?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

17.2 Glossary

TermMeaning
OLTPOnline transaction processing: many short reads and writes
RPO / RTOMaximum tolerable data loss / time to restore service
Keyset paginationPaging by the last seen key instead of an offset
Expand and contractZero-downtime migration pattern in additive and subtractive phases
[Term][Meaning]

17.3 References

ReferenceUse
[DBMS documentation, version]Types, partitioning, isolation behaviour
[Data dictionary]Business definitions of each column
[Internal database standards]Naming and review rules

Standard and licence note

Based on common industry practice for database design documentation: conceptual, logical and physical modelling, normalisation, indexing and operational design. Original text written for this collection; example values are illustrative and not tuning advice for any specific product. Template licence: MIT.

Ähnliche Vorlagen