What Is a .dbs File? The DbSchema Design Model Explained

For the developer who finds a .dbs file in a pull request and wants to read the schema change without opening DbSchema.

On this page

A pull request touches a file called sports.dbs, and the diff is XML. That file is the DbSchema design model: the tables, columns, indexes, foreign keys and diagram layouts of one database design, held in a single text file that needs no server to open. DbSchema shows it as diagrams. Any text editor shows it as XML, and so does the diff view of your review tool.

What a .dbs file stores

The file holds a design, not a picture of one. Everything DbSchema needs to redraw the schema, generate SQL for it and compare it against a server is in there: the tables with their columns, types, lengths, defaults and identity settings; the primary and unique keys; the check constraints; the foreign keys; the comments written on any of them; the virtual foreign keys that exist only in the model; and the layout of every diagram drawn over the schema.

The format is XML, the same tag format configuration files use everywhere. That one choice is what the rest of this article rests on: a .dbs file diffs, merges and greps like source code, because it is text.

An annotated excerpt from a .dbs file

Below is a trimmed excerpt from a real .dbs file written against a PostgreSQL schema of teams and players. Four things in it are where readers usually guess wrong.

<?xml version="1.0" encoding="UTF-8" ?>
<project name="sports" database="PostgreSQL" id="6f6c2a3e-1b1a-4f2e-9b6a-7c1f9a2e3d4b" >
	<schema name="public" catalogname="sports" >
		<table name="teams" row_count="0" spec="" >
			<comment><![CDATA[Sports teams participating in the league]]></comment>
			<column name="id" type="integer" length="32" mandatory="y" >
				<identity><![CDATA[GENERATED BY DEFAULT AS IDENTITY]]></identity>
			</column>
			<column name="name" type="varchar" length="100" mandatory="y" >
				<comment><![CDATA[Team name]]></comment>
			</column>
			<column name="city" type="varchar" length="100" />
			<index name="pk_teams" unique="PRIMARY_KEY" >
				<column name="id" />
			</index>
		</table>
		<table name="players" row_count="0" spec="" >
			<column name="id" type="integer" length="32" mandatory="y" />
			<column name="team_id" type="integer" length="32" mandatory="y" />
			<column name="name" type="varchar" length="100" mandatory="y" />
			<index name="pk_players" unique="PRIMARY_KEY" >
				<column name="id" />
			</index>
			<fk name="fk_players_team" to_schema="sports.public" to_table="teams" >
				<fk_column name="team_id" pk="id" />
			</fk>
		</table>
	</schema>
	<layout name="sports_overview" id="9a1e4c2d-5f3b-4a6e-8c1d-2b3a4f5e6d7c" show_column_type="y" show_relation="columns" >
		<entity schema="sports.public" name="teams" color="C1D8EE" x="400" y="80" />
		<entity schema="sports.public" name="players" color="C7F4BE" x="80" y="320" />
	</layout>
</project>

Tables sit inside one schema element, and each table carries its own columns, keys and relations. There is no separate column section to cross-reference, so everything about players is between its opening and closing tag. A relation is an fk element inside the table that owns the foreign key, with one fk_column per column pair, which means the way to find what points at teams is to search the file for to_table="teams".

Primary keys are the third surprise. A key is written as an index element with unique="PRIMARY_KEY", not as an attribute on the column, so id looks like an ordinary integer column until you read the index below it. Nullability is the reverse of what SQL trains you to expect: mandatory="y" marks the column NOT NULL, and its absence marks the column nullable.

The fourth is the diagram. Layouts live in their own layout elements after the schema, one per diagram, each holding an entity element per box with the coordinates and the colour it was drawn in. Model and drawing are stored apart, which is why moving a table on the canvas never changes the schema, and why one project file can hold as many diagrams over the same tables as you want to draw: one for orders, one for billing, one for the whole thing.

The DbSchema window with a PostgreSQL model open, showing the company diagram with transactions, orders, customers and products laid out and connected by foreign key lines

Virtual foreign keys in the model file

Where the database declares no foreign key, or where the relation runs between views, you can draw one anyway by dragging a column onto the column it refers to; DbSchema asks whether to make it real or virtual. A virtual foreign key is saved to the design model and never created in the database, and no SQL is generated for it. The Relational Data Editor and the Query Builder then follow it exactly as they follow a declared one.

Reading a .dbs diff in a pull request

Because the file is XML, a schema change arrives in review as a readable diff, and you can approve or reject it without opening DbSchema. Read it in this order.

  1. Look for added or removed table blocks first. A whole table appears or disappears as one contiguous block, which is the largest change the file can carry.
  2. Read the changed column lines next. A widened field shows up as a changed length, and a nullable column becoming required shows up as mandatory="y" appearing on it.
  3. Then read the fk elements. A new one adds a constraint the database will enforce on every write, so it deserves the closest reading in the diff.
  4. Treat changes inside a layout element as cosmetic. Moved boxes change only x, y and color, so a diff that touches nothing else is a tidy-up of the drawing.
  5. Watch for renames. XML has no rename operation, so a renamed table reads as one block deleted and another added, and only the surrounding context tells you which it was.

Why the model is independent of the database

DbSchema Database Designer

The file records a design, not a connection. It names its target engine in the project element, and nothing in it requires a server to be reachable, so you can open, edit and review a .dbs file with no database running anywhere. Retarget it later from Model → Model Properties by changing the RDBMS field, and DbSchema remaps the data types and shows you the conversion before you save; triggers, functions and stored procedures are the exception, and have to be rewritten by hand.

Saving the model to a file is a Pro feature. The free Community Edition connects to a database, reverse-engineers it and draws interactive diagrams, and Pro is what writes the design to disk as .dbs.

The .dbs file in a Git repository

Commit the .dbs file next to the code that depends on it and the schema gets the same history, branches and review as everything else. DbSchema has a Git client of its own, opened with Git — Collaborative Design from the Model menu, so the model is cloned, staged, committed and pushed without leaving the application. One repository can hold several .dbs files, one per database or per component, and each is opened from the Model menu like any other model. For the wider workflow, including how it compares with versioning migration scripts, see the guide to database design tools with Git.

The DbSchema Git dialog with a repository's commit history and the sakila.dbs model file staged for commit

Schema comparison against a live database

Point a saved model at a server, click Refresh Model from Database, and the Synchronization Dialog lists every difference in both directions. Each one is decided on its own: apply it to the database, take the server's version into the model, or have DbSchema write the migration SQL for you to run later. The same dialog compares two .dbs files, which is how you read what changed between two branches of a design before either reaches a database. The procedure is walked through in the offline design and schema synchronization guide.

The Synchronization Dialog listing a table that exists in the DbSchema design model and is missing from the database, with the CREATE TABLE statement that would create it

Generating documentation from the model

Because the file already holds the constraints and the comments, it is what DbSchema reads to produce documentation: HTML5, PDF or Markdown, generated from the model rather than from a live connection. The HTML5 output opens in any browser with no install behind it, and the descriptions written on tables and columns come through as mouse-over tooltips. The formats and the options are covered in the walkthrough on generating database documentation.

A page of generated HTML5 documentation, with the diagram at the top and the table and column details listed underneath

Open a .dbs file once in a text editor and the diffs stop being opaque: tables carry their own columns, keys and relations, primary keys are indexes, and the drawing sits apart from the schema in its own layout elements. Download DbSchema at https://dbschema.com/download.html and reverse-engineer your database into diagrams in the free Community Edition; saving that design as a .dbs file, and everything above that reads one, is Pro.

Open a .dbs model yourself

DbSchema reverse-engineers your database into an interactive ER diagram in the free Community Edition. Saving the project to a .dbs file, offline design and schema synchronization are Pro.