How to Write DBML: A Guide to Diagramming Your Database Schema
DBML (Database Markup Language) is a small, plain-text language for describing a database schema — tables, columns, and the relationships between them — that’s built specifically to be turned into a diagram, rather than run against a database. You write it once and get a readable ER diagram out of it, without dragging boxes around by hand or reverse-engineering one from an existing database.
This guide walks through the syntax one piece at a time — tables, columns, column settings, and relationships — then how to work with it efficiently once a schema has more than a couple of tables.
Defining a table
A table is a `Table` block with a name and, inside braces, one line per column. Each column line is just a name followed by a type — no commas, no semicolons.
- Table users {
- id integer
- username varchar
- created_at timestamp
- }
Column settings
Square brackets after a column’s type attach settings to it — constraints and metadata that shape how the column is drawn and (if you export the DBML elsewhere) how a real database would enforce it. Multiple settings are comma-separated inside one pair of brackets.
- primary key (or the shorthand pk) — marks the column as the table’s primary key.
- not null — the column is required.
- unique — no two rows can share a value.
- increment — an auto-incrementing value, typically paired with a primary key.
- default: value — a default value, e.g. default: 0 or default: `now()` for an expression.
- note: 'text' — a short annotation shown alongside the column, useful for documenting intent without a separate wiki page.
Relationships with Ref
A `Ref` line is what turns a set of separate tables into a connected diagram — it declares a foreign key relationship and draws the connecting line between the two tables. The symbol in the middle says which side is the "many": `>` means the left table has many rows per one row on the right, `<` is the reverse, and `-` is one-to-one.
Refs can be declared inline, right after the table they belong to, or gathered at the bottom of the file — both are read identically. For a schema with more than a handful of relationships, grouping them at the end tends to be easier to scan than hunting through each table for its foreign keys.
- Ref: posts.user_id > users.id
- Ref: comments.post_id > posts.id
- Ref: profiles.user_id - users.id
Indexes and notes
An `indexes` block inside a table declares which columns are indexed, including composite indexes across multiple columns — useful for documenting query performance decisions alongside the schema they apply to, rather than in a separate migration file no one reads.
A standalone `Note` (either at the table level or as its own top-level block) documents intent that doesn’t belong on any single column — why a table exists, a constraint the diagram can’t express, a TODO for a future migration.
- indexes {
- (user_id, created_at)
- email [unique]
- }
Working efficiently: templates, import/export, and sharing
Starting from a blank editor for a common shape — a blog, an e-commerce schema, a basic users/posts setup — usually costs more time than it saves. Starting from a template and renaming tables to match your actual schema gets to a working diagram faster than typing every table from scratch.
Import an existing .dbml file to pick up an export from elsewhere, or export the current schema as DBML, PNG, or SVG once it’s ready to share or paste into documentation. A share link works without any account or server round-trip — it compresses the DBML itself into the URL, so opening the link reconstructs the exact schema on the other end.
Everything — the schema text and the diagram layout you’ve dragged tables into — is saved to this browser’s local storage automatically. Nothing is uploaded anywhere unless you explicitly export or share it.
FAQ
Do I need a database connection to use DBML?
No — DBML is just text describing a schema; it never connects to a real database. You can design a schema entirely on paper (or in the editor) before a database exists, or document one that already does, without giving the tool any credentials or access.
Does DBML support enums?
DBML’s `enum` syntax is recognized without erroring, but it isn’t drawn on the diagram — so it’s fine to include for documentation purposes, but don’t rely on it to show up visually. Tables, columns, column settings, and Ref relationships are what actually render.
What’s the difference between `>` and `<` in a Ref?
They describe the same relationship from opposite directions, not two different relationship types. `posts.user_id > users.id` and `users.id < posts.user_id` mean exactly the same thing: many posts reference one user. Pick whichever direction reads more naturally for the line you’re writing.
Can I turn an existing database into a DBML diagram?
Only if you already have (or can export) its schema as DBML — this tool renders DBML you provide, it doesn’t connect to or introspect a live database. Some database clients and ORMs can export a schema as DBML directly, which you can then paste in as a starting point.
Put this into practice with a real schema.
Try the free DBML Diagram Builder