OutputsSVG

SVG

The command line, and toSvg in code, draw the diagram with resin's own renderer. It lays out the tables with ELK's layered algorithm. Left to right, the default, there is a port on every column row, so each connector runs from a foreign key row to the primary key row it points at.

shop.erdOpen in playground
external table users "Accounts service" {
  id  bigint  pk
}

table orders "Customer orders" {
  id       bigint   pk
  user_id  bigint   ~> users
  status   varchar  enum(PENDING, PAID)  index
}

table payments {
  id        bigint  pk
  order_id  bigint  uk  -> orders
  memo      text?
}
The diagram resin draws for shop.erdThe diagram resin draws for shop.erd

Cards

A card has the table's name and description in its header, then one row per column: a key label in a gutter (PK, UK or FK), the column's name with its tags (ENUM, ENC, IX, and FK on a primary key) after it in small capitals, its description, and its type in a left-aligned column at the right. The descriptions of a card all start at one place, and so do its types. A nullable column is marked NULL after its type, in the same square chip as a table's tag. Composite constraints are listed under the rows.

The hide option leaves parts of the rows out: the key labels (keys), tags, descriptions, types and nulls. The column's name always stays, and a card narrows to what is left. Embedding has a control for choosing them.

External tables have a dashed border and an EXTERNAL tag. Audit tables are folded into an ENVERS tag unless they are expanded.

Services

A service is an area around its tables, with a faint tint, an even edge and its name and description at the top left. ELK lays a service out as a node that holds its cards, so the tables of a service stay together and connectors cross from one service to another. With a glass look, services take hues in the order they are declared (teal, violet, amber, rose, sky, lime, then again); graphite draws them in ink alone. The tint stops at the cards, so glass painted under the SVG is never tinted.

The fold option draws the services it names as one card each, to see how a schema's services depend on each other. A folded card has the service's name and description in its header, in the service's hue, with an edge in the same hue, and one row per table: the table's name and its number of columns, with EXTERNAL or ENVERS where the table's own card would have them. A service whose tables are all external has a dashed border and an EXTERNAL tag, as an external table does. References inside the service are counted under the rows, as 5 references inside. A reference that leaves the service runs from the row of its table (top to bottom, from its card), and references of one kind between the same two tables share one connector, which then has no mark or number at the row's end. Tables of services that are not folded are drawn as usual, so a drawing can open one service and fold the ones around it. resin --services folds every service and draws the tables outside every service by name only.

Changes

A model from diff carries what changed, and the drawing marks it: added in green, removed in red and faded, changed in amber, on the card's border and a tag in its header, at the left of a column's row, and on connectors.

Connectors

Solid for foreign keys, dashed for logical references. Both ends are marked in crow's foot, with the number beside the mark:

ends.erdOpen in playground
table users {
  id  bigint  pk
}

table profiles "At most one per user" {
  user_id  bigint  pk  -> users
}

table orders "Any number per user" {
  id       bigint  pk
  user_id  bigint  -> users  index
}

table reviews "Edited by a user, or by no one" {
  id         bigint   pk
  editor_id  bigint?  -> users  index
}

table avatars "At most one per user, or none" {
  id       bigint   pk
  user_id  bigint?  uk  -> users
}
Every kind of end on one primary key: NOT NULL above, nullable belowEvery kind of end on one primary key: NOT NULL above, nullable below
End Mark Number Means
Primary key Two bars 1 The referencing column is NOT NULL: every row has exactly one parent
Primary key A bar and a ring 0..1 The referencing column is nullable: a row may have no parent
Foreign key A crow's foot N One-to-many: a parent may have many rows
Foreign key A bar 1 One-to-one: the referencing column is uk or its table's only primary key

Left to right, connectors from one primary key row share their first stretch. When both NOT NULL and nullable columns reference a row, the two kinds leave it 12 units apart, the NOT NULL ones above, so each stretch carries one mark. Connectors are right-angled by default, or S-bends with edges: "curved", which run straight out of each card before they bend and keep the routed path wherever an S-bend would cross another card.

The drawing runs left to right: a referenced table sits to the left of the tables that reference it, and a connector joins the two rows. With direction: "down" it runs top to bottom: a referenced table sits above them, and a connector joins the two cards, from the bottom of one to the top of the other, since a row has ends only at the sides of its card. A connector still names the columns it joins in data-ac and data-bc, a composite reference is one connector, and a connector that crosses the top of a service's area breaks behind the service's name.

Looks

Look Background
graphite None, the default. Ink is currentColor, so the drawing reads on any page
aurora-dark, aurora-light Ribbons of light under a sky of stars
silk-dark, silk-light Folds of color
caustic-dark, caustic-light Light through water

With a glass look the cards are frosted glass over the background, which the SVG draws as a still picture.

Options

Option Values Default
look One of the looks above graphite
columns all; keys for key and reference columns only; none for the table names alone, with the connectors between the headers all
audit collapse, or expand to draw revinfo and *_aud collapse
fold Names of services to draw as one card each, a row per table none
edges angular or curved angular
direction right, or down to stack the tables top to bottom, connectors joining the cards right
hide Parts of the rows to leave out: keys, tags, descriptions, types, nulls (CARD_PARTS lists them) none
standalone Adds a style that picks the ink color from the reader's theme, for files embedded with <img> false
stage false leaves out the background and the glass, for a page that paints them itself true
idPrefix Prefixes every id, so several drawings can share a page rz-

Hooks for viewers

A table is g.rz-t[data-t], a service g.rz-svc[data-svc] with its label in g.rz-svc-head, a table's header g.rz-head, a column row g.rz-c[data-c], and a connector g.rz-r, with data-a and data-ac for its primary key side and data-b and data-bc for its foreign key side. A folded service is a g.rz-t with data-svc, and data-t is service and its name in backticks (service `ordering`), which no table's identity can be; each of its rows has the table's identity in data-table. A page can fade or highlight parts of the drawing with CSS alone.

Deterministic

Text is never measured. Widths follow fixed rules, so the same input gives the same SVG in a browser and on the command line.

Composite constraints

Left to right, composite references draw one connector per ordered column pair while retaining one semantic relation in the model; top to bottom, they draw one. Their connectors carry data-acs and data-bcs JSON arrays for coordinated focus. Cards include the constraint in their footer, and Keys keeps every member column. Service-owned cards display the short table label and use the qualified identity in data-t and layout boxes.