By Arthur Teboul//10 min read/Tutorial

Mermaid ER Diagram: Complete Syntax Guide with Examples

Mermaid ER diagrams let you document database schemas and data models in plain text, inside the same Markdown files as your code documentation. Search interest in "mermaid er diagram" has grown 84% year-over-year (DataForSEO, 2026) — development teams are moving away from screenshot-based database diagrams toward version-controlled, text-based alternatives. MacMD Viewer ($19.99, native macOS SwiftUI app) renders Mermaid ER diagrams locally in .md files with no plugins or internet connection. This guide covers the full erDiagram syntax with working examples you can copy directly into your documentation.

TL;DR: Start with erDiagram, define entities using ENTITY { type name PK }, connect them with ||--o{ for one-to-many relationships. Use -- for identifying relationships and .. for non-identifying. Preview locally with MacMD Viewer or online at mermaid.live.

What Is a Mermaid ER Diagram and When Should You Use It?

A Mermaid ER diagram is a text-based entity-relationship diagram that describes database tables, their columns, and how they relate to each other. You write it inside a ```mermaid code fence starting with erDiagram, and any Mermaid renderer produces a visual diagram from that text.

ER diagrams are useful in three primary contexts:

  • Database design — sketch the schema before writing migrations, catch relationship mistakes early
  • Technical documentation — explain the data model to new engineers without maintaining a separate diagram file
  • Code review — include an ER diagram in a PR to show how a migration changes the schema

Compared to dedicated tools like dbdiagram.io or draw.io, the Mermaid approach has one decisive advantage: the diagram lives in your repository as plain text, so Git tracks every change. When a column is renamed or a relationship is added, the diff shows exactly what changed — you never end up with a stale PNG that no longer matches the actual schema.

ER diagrams have been stable in Mermaid since v8, and every current renderer supports them. For related Mermaid diagram types, see the Mermaid flowchart syntax guide and the Mermaid sequence diagram guide.

How Do You Write Basic Mermaid ER Diagram Syntax?

An ER diagram starts with erDiagram, followed by entity blocks and relationship lines. Here is the minimal structure that renders a valid diagram:

erDiagram
    USER {
        int id PK
        string email UK
        string name
        date createdAt
    }
    POST {
        int id PK
        int userId FK
        string title
        string body
        datetime publishedAt
    }
    USER ||--o{ POST : "writes"

This produces two entity boxes connected by a one-to-many line labeled "writes". The USER entity has four attributes: an integer primary key, a unique email, a name, and a creation date. The POST entity has a foreign key back to USER.

Every entity block follows the same pattern:

ENTITY_NAME {
    type attributeName optionalKey
    type attributeName optionalKey
}

Entity names are typically uppercase by convention, though Mermaid accepts any case. Attribute types are free-form strings — Mermaid does not validate them against a schema, so you can write varchar(255), string, or TEXT and the diagram renders identically. Stick to a consistent set of types across your codebase.

Supported Attribute Types

Common types used in Mermaid ER diagrams:

TypeUse Case
intInteger identifier or counter
bigintLarge integer (user IDs at scale)
stringShort text (names, slugs, status)
textLong text (body content, descriptions)
booleanTrue/false flags
float / decimalNumeric values with decimals
dateDate without time
datetimeFull timestamp
uuidUUID primary key
jsonJSON blob column

How Do You Add Keys to ER Diagram Attributes?

Mermaid supports three key markers that appear after the attribute name. Add them as a suffix with a space:

MarkerMeaning
PKPrimary key
FKForeign key
UKUnique key (unique constraint)

An attribute can have multiple markers if needed — int id PK is the most common pattern, but string email UK marks a unique constraint and int orderId FK marks a foreign key reference.

erDiagram
    CUSTOMER {
        uuid id PK
        string email UK
        string firstName
        string lastName
        date createdAt
    }
    ORDER {
        uuid id PK
        uuid customerId FK
        decimal totalAmount
        string status
        datetime placedAt
    }
    CUSTOMER ||--o{ ORDER : "places"

Comments use %% at the start of a line, identical to other Mermaid diagram types:

%% This diagram documents the e-commerce schema v2
erDiagram
    PRODUCT {
        int id PK
        string sku UK
    }

What Does the Relationship Notation Mean?

The relationship line syntax is the most distinctive part of Mermaid ER diagrams. The notation ||--o{ looks cryptic at first, but each character has a specific meaning that maps directly to standard crow's foot notation.

A relationship line has five components:

ENTITY1  LEFT_MARKER -- RIGHT_MARKER  ENTITY2 : "label"

The -- (double dash) is the line style. Use -- for an identifying relationship (the child depends on the parent for its identity) or .. for a non-identifying relationship (both entities exist independently).

Cardinality Markers

Each side of the line takes a two-character cardinality marker:

MarkerMeaningDescription
||Exactly oneMandatory, singular
o|Zero or oneOptional, singular
|{One or moreMandatory, plural
o{Zero or moreOptional, plural

Reading ||--o{ from left to right: exactly one (on the left entity) — identifying relationship — zero or more (on the right entity). This is a standard one-to-many.

Full Notation Reference

NotationCardinalityReal-World Example
||--||One-to-oneUSER has one PROFILE
||--o|One-to-zero-or-oneUSER has optional BILLING_ADDRESS
||--o{One-to-zero-or-manyCUSTOMER places zero or more ORDERS
||--|{One-to-one-or-manyORDER contains one or more ORDER_ITEMS
o{--o{Many-to-manyPRODUCT belongs to many CATEGORIES
||..o{Non-identifying one-to-manyPOST has zero or more COMMENTS

The label after the colon is required in Mermaid ER syntax. Wrap it in double quotes: : "places", : "contains", : "belongs to". The label describes the relationship from the perspective of the left entity.

What Does a Real-World ER Diagram Look Like?

Here is a complete e-commerce schema covering the four core tables most production systems share: customers, products, orders, and order line items.

erDiagram
    CUSTOMER {
        uuid id PK
        string email UK
        string firstName
        string lastName
        string phone
        date createdAt
    }
    ADDRESS {
        uuid id PK
        uuid customerId FK
        string street
        string city
        string country
        string postalCode
        boolean isDefault
    }
    PRODUCT {
        uuid id PK
        string sku UK
        string name
        text description
        decimal price
        int stockQuantity
        boolean isActive
    }
    ORDER {
        uuid id PK
        uuid customerId FK
        uuid shippingAddressId FK
        string status
        decimal subtotal
        decimal shippingCost
        decimal totalAmount
        datetime placedAt
    }
    ORDER_ITEM {
        uuid id PK
        uuid orderId FK
        uuid productId FK
        int quantity
        decimal unitPrice
        decimal lineTotal
    }
    CUSTOMER ||--o{ ADDRESS : "has"
    CUSTOMER ||--o{ ORDER : "places"
    ADDRESS ||--o{ ORDER : "ships to"
    ORDER ||--|{ ORDER_ITEM : "contains"
    PRODUCT ||--o{ ORDER_ITEM : "included in"

This diagram captures the full purchase flow: customers own addresses and place orders, orders are shipped to one address and contain one or more items, and each item references the product it sold. The ORDER_ITEM table uses identifying relationships (--) because a line item cannot exist without its parent order. The ADDRESS to ORDER link is also identifying for the same reason.

For a blog platform, the schema looks like this:

erDiagram
    USER {
        int id PK
        string username UK
        string email UK
        string passwordHash
        datetime createdAt
    }
    POST {
        int id PK
        int authorId FK
        string title
        string slug UK
        text body
        string status
        datetime publishedAt
    }
    COMMENT {
        int id PK
        int postId FK
        int authorId FK
        text body
        datetime createdAt
    }
    TAG {
        int id PK
        string name UK
        string slug UK
    }
    POST_TAG {
        int postId FK
        int tagId FK
    }
    USER ||--o{ POST : "writes"
    USER ||--o{ COMMENT : "authors"
    POST ||--o{ COMMENT : "has"
    POST ||--o{ POST_TAG : "tagged with"
    TAG ||--o{ POST_TAG : "applied to"

The POST_TAG junction table implements the many-to-many relationship between posts and tags. Both foreign keys together form the composite primary key, which is common for join tables.

What Are the Most Common ER Diagram Mistakes?

Four mistakes appear repeatedly in Mermaid ER diagrams written by developers new to the syntax.

Wrong relationship direction. The label should read naturally from left to right: CUSTOMER ||--o{ ORDER : "places" — a customer places orders, not the other way around. Reversing the entities reverses the cardinality meaning, which produces a diagram that renders but communicates the opposite of the intended relationship.

Missing relationship label. The label after : is not optional in Mermaid's ER syntax. Omitting it throws a parse error. Use a short verb phrase: "has", "contains", "belongs to".

Confusing -- and ... Use -- (identifying) when the child row has no meaning without the parent — an order item without an order is meaningless. Use .. (non-identifying) when both can exist independently — a product exists even if no orders have ever included it.

Spaces in entity names. Entity names cannot contain spaces. Use ORDER_ITEM or OrderItem, not ORDER ITEM. The underscore convention matches SQL naming and is the most common pattern in the wild.

Where Do Mermaid ER Diagrams Render?

Mermaid ER diagrams render anywhere the Mermaid.js library is present:

PlatformNotes
MacMD ViewerNative macOS app, renders locally, no internet needed. Download here.
GitHubRenders natively in .md files since 2022 — push your diagram, GitHub displays it.
GitLabBuilt-in Mermaid rendering in Markdown files and wikis.
NotionUse the /code block, select Mermaid as the language.
ConfluenceRequires the Mermaid for Confluence plugin. See the Mermaid Confluence guide.
Mermaid Live EditorFree browser playground at mermaid.live. Best for iterating.
ObsidianRenders natively — no plugin needed.
VS CodeUse the Markdown Mermaid extension with Cmd+Shift+V.

For a full comparison of browser-based options, see online Mermaid diagram tools. If you want to export diagrams as PNG or SVG files, the Mermaid live editor guide covers the export workflow. You can also use the Mermaid viewer roundup to compare dedicated rendering tools.

How Does Mermaid Compare to Dedicated ER Diagram Tools?

Dedicated tools like dbdiagram.io, draw.io, and Lucidchart offer richer visual editing: drag-and-drop layout control, auto-generated SQL from your schema, and export to multiple formats. For teams that need a polished standalone diagram, those tools are the right choice.

Mermaid wins when your diagram lives inside documentation. Three specific advantages:

  1. Version control — the diagram is a text file, so git diff shows exactly what changed between schema versions. A PNG has no diff.
  2. Documentation co-location — the schema lives next to the code in the same repository. No separate diagramming account, no broken links to external tools.
  3. Renderer ubiquity — GitHub, GitLab, Notion, Obsidian, and VS Code all render Mermaid natively. Your diagram is readable anywhere your Markdown file opens.

The tradeoff is layout control. Mermaid places entities automatically — you cannot manually position boxes. For large schemas (30+ tables), auto-layout produces cluttered output. In that case, split the schema into domain-specific sub-diagrams: one for user management, one for orders, one for inventory.

MacMD Viewer is the fastest local option on macOS: open a .md file and the ER diagram renders immediately. The QuickLook extension also renders Mermaid when you press Space on a .md file in Finder — useful when reviewing schema documentation without opening any app.

Conclusion

Mermaid ER diagram syntax is compact: declare erDiagram, define entities with typed attributes and key markers, connect them with cardinality notation. The ||--o{ relationship syntax covers every cardinality combination once you know that || means exactly-one, o| means zero-or-one, |{ means one-or-more, and o{ means zero-or-more. Use -- for identifying relationships and .. for non-identifying.

Copy the e-commerce or blog schema examples above, replace entity names and attributes with your own tables, and you have a working database diagram that lives in version control. Preview locally with MacMD Viewer for instant rendering on Mac, or iterate in the browser at mermaid.live. For more Mermaid diagram types, see the complete Mermaid diagram guide and the Mermaid flowchart syntax reference.

Ready to read Markdown beautifully?

Native macOS viewer with Mermaid diagrams, syntax highlighting, and QuickLook. One-time purchase, no subscription.

Buy for $19.99

Continue reading with AI

Summarize in ChatGPT🔍Research in PerplexityAsk Google AI

Content licensed under CC BY 4.0. Cite with attribution to MacMD Viewer.

Related Articles

Tutorial

Mermaid Class Diagram: Complete Syntax Guide with Examples (2026)

Learn Mermaid class diagram syntax end-to-end — attributes, methods, visibility modifiers, all 8 relationship types, cardinality, annotations, and a full e-commerce OOP example.

Guide

Mermaid Diagrams: Complete Guide for Developers (2026)

Mermaid diagram viewer searches up 1,015% YoY (DataForSEO, 2026). Everything about Mermaid.js — syntax, diagram types, tools, viewers, and best practices.

Tutorial

Mermaid Sequence Diagram: Complete Syntax Guide (2026)

Mermaid sequence diagram searches up 60% YoY (DataForSEO, 2026). Learn the full syntax — participants, arrows, activations, loops, alt blocks, and notes.