This sample is a logical schema diagram for a small support-desk application on PostgreSQL. It shows each table with its columns and data types, the primary and foreign keys that link them, and the indexes and constraints that make the common queries fast and the data correct.
1. The Diagram
Unlike a conceptual ER diagram, this one is close to DDL: every column has a type, and keys and indexes are explicit.
app_user holds everyone: customers and agents, told apart by role. email has a unique key so it can be used to log in.
ticket has two foreign keys to app_user. requester_id is mandatory (bars at the user end); assignee_id is nullable (circle), because new tickets are unassigned.
ticket_comment belongs to one ticket and one author. Its ticket_id index makes "load the thread" fast.
ticket_tag (highlighted) is the junction table for the many-to-many between tickets and tags; its primary key is the pair of foreign keys.
The green box lists indexes. ix_ticket_status is composite, matching the main agent query: open tickets, oldest first.
The grey box lists CHECK constraints and cascade rules that the lines alone cannot show.
2. How to Read It
Table boxes list columns top-down with key markers on the left and types on the right. Relationship lines use crow's foot endings; where it helps, a line leaves the box next to the FK column it represents. Indexes and constraints go in side boxes so the tables stay readable.
3. Variant: Conceptual View
The conceptual view hides columns and implementation detail, which suits business conversations. The logical view adds attributes, keys and types; a physical view would add storage details such as partitions and tablespaces. Keep both: the simple one for discussions, the detailed one for code review.
4. Pros, Cons, and When to Use
Pros
Close enough to DDL to review migrations against.
Shows keys, types and NULL-ability in one place.
Index notes connect the model to real query patterns.
Can be reverse-engineered from a live database (DBeaver, DataGrip, SchemaSpy).
Readable by developers, DBAs and analysts alike.
Cons
Too detailed for business stakeholders.
Goes stale quickly unless generated from the database or migrations.
Large schemas need splitting by subject area.
Engine-specific types make it less portable.
When to use
Reviewing a migration or new feature's tables.
Documenting an existing database for a new team.
When not to use
Early requirements work (start conceptual).
Analytical marts (a star schema diagram communicates better).
5. As Diagrams-as-Code
MermaiderDiagram with types and keys:
erDiagram
app_user ||--o{ ticket : requests
app_user |o--o{ ticket : "assigned to"
ticket ||--o{ ticket_comment : has
app_user ||--o{ ticket_comment : writes
ticket ||--o{ ticket_tag : tagged
tag ||--o{ ticket_tag : labels
app_user {
bigint user_id PK
varchar email UK
varchar role
}
ticket {
bigint ticket_id PK
bigint requester_id FK
bigint assignee_id FK "nullable"
varchar status
smallint priority
}
ticket_tag {
bigint ticket_id PK, FK
int tag_id PK, FK
}
Mermaid has no index syntax; keep indexes in DDL or a DBML indexes { } block.