Database Documentation: Tools, a Template and Examples

· 10 MIN

TL;DR: Good database documentation is a data dictionary (what every table and column means), an ER diagram (how tables connect) and a few lines of business rules, generated from the live schema so it never goes stale. Store descriptions as native comments in the database, then let a free generator such as tbls, SchemaSpy or dbdocs turn them into a browsable site on every merge.

Database documentation is the written description of a database's structure and meaning: each table's purpose, each column's type, unit and allowed values, the keys that link tables, and who owns the data. The fastest way to build it in 2026 is to write descriptions where the schema lives (PostgreSQL COMMENT ON, MySQL COMMENT, SQL Server extended properties) and generate the rest. Free generators read those comments plus the catalog and output HTML or Markdown with diagrams: tbls for CI-friendly Markdown, SchemaSpy for a static HTML site, and dbdocs for a hosted, shareable page. Paid catalogs like Dataedo start at $18,000 a year and only make sense once you have many databases and a governance team.

Below: the resources grouped by kind, a copyable template, real examples worth modelling, and a start-here path by team size.

Comments written in a migration flow through CI into regenerated documentation on every merge
FIG 01 — The docs change in the same pull request as the schema.

What should database documentation include?

Database documentation should include five things, in this order of usefulness:

  1. A data dictionary. One row per column: table, column, type, nullable, description, example value, and units or allowed values. This answers "what does status = 3 mean?", which is the question people actually ask.
  2. Table purpose. One or two sentences per table: what a row represents ("one row per checkout, refunds live in refunds") and the grain.
  3. Relationships. Primary and foreign keys and an ER diagram, so readers know how to join orders to customers without guessing.
  4. Ownership and lineage. Which team or service writes the table, and when it was introduced. GitLab records feature_categories and introduced_by_url per table for exactly this reason.
  5. Business rules and gotchas. Soft deletes, money stored in cents, time zones, columns that are deprecated but still populated.

Skip prose that restates the column name ("created_at: the created at date"). A good description says something the schema can't: units, edge cases, the source system.

Native comments: the free documentation layer every database has

Write descriptions into the database first. Every generator below reads them, and they travel with backups and migrations.

-- PostgreSQL: put the meaning next to the schema, inside the migration
COMMENT ON TABLE orders IS 'One row per completed checkout. Refunds live in refunds, not here.';
COMMENT ON COLUMN orders.total_cents IS 'Order total in cents, after discounts, before tax.';
COMMENT ON COLUMN orders.status IS '1 = paid, 2 = shipped, 3 = cancelled by customer.';
-- SQL Server equivalent for one column
EXEC sys.sp_addextendedproperty
  @name = N'MS_Description',
  @value = N'Order total in cents, after discounts, before tax.',
  @level0type = N'SCHEMA', @level0name = N'dbo',
  @level1type = N'TABLE',  @level1name = N'orders',
  @level2type = N'COLUMN', @level2name = N'total_cents';

If you are new to how a schema is organised, our schema glossary entry covers the basics.

Which free tools generate database documentation automatically?

These database documentation tools connect to a live database (or a schema file), read the catalog and your comments, and output docs with diagrams. All are free or have a free tier.

Docs for analytics models and larger teams

Copyable data dictionary template

Use these columns. Keep the description to one sentence that a new hire could act on.

tablecolumntypenulldescriptionexampleowner
ordersidbigintnoPrimary key.48213checkout
orderscustomer_idbigintnoFK to customers.id.9921checkout
orderstotal_centsintegernoTotal in cents, after discounts, before tax.4599checkout
ordersstatussmallintno1 paid, 2 shipped, 3 cancelled by customer.2fulfilment
ordersdeleted_attimestamptzyesSoft delete. Filter IS NULL in every report.nullcheckout
A data dictionary row per column turns cryptic orders fields into plain meanings
FIG 02 — The schema says what a column is; the dictionary says what it means.

You don't have to fill it by hand. This PostgreSQL query exports the template straight from the catalog, comments included, so you can paste it into a sheet:

-- PostgreSQL: data dictionary from the live schema
SELECT c.table_name,
       c.column_name,
       c.data_type,
       c.is_nullable,
       col_description(format('%I.%I', c.table_schema, c.table_name)::regclass,
                       c.ordinal_position) AS description
FROM information_schema.columns c
WHERE c.table_schema = 'public'
ORDER BY c.table_name, c.ordinal_position;
-- MySQL: same output, comments come from COLUMN_COMMENT
SELECT table_name, column_name, column_type, is_nullable, column_comment
FROM information_schema.columns
WHERE table_schema = DATABASE()
ORDER BY table_name, ordinal_position;

Empty description cells are your to-do list. For more on the concept itself, see our data dictionary definition, and if you need to find every database on a server first, list all databases in Postgres.

What does good sample database documentation look like?

Model these real, public examples rather than a blank page:

What the good ones share: every table has a one-line purpose, descriptions carry units and enum meanings, and the docs live in the repo so a schema change without a doc change gets noticed in review.

How do you keep database docs up to date?

Make the documentation a by-product of shipping, not a separate project:

  1. Write COMMENT ON (or COMMENT, or sp_addextendedproperty) in the same migration that adds the column.
  2. Add a .tbls.yml with your dsn: and docPath:, and turn on requireColumnComment and requireTableComment under lint:.
  3. Run tbls lint and tbls diff in CI so a pull request with an undocumented column fails.
  4. Regenerate the docs on merge to main (the k1low/setup-tbls@v1 GitHub Action does this) and commit or publish the output.
  5. Check tbls coverage monthly and fix the tables at 0% first.
# .tbls.yml
dsn: postgres://dbuser:dbpass@localhost:5432/app
docPath: doc/schema
lint:
  requireTableComment:
    enabled: true
  requireColumnComment:
    enabled: true
    exclude:
      - id
      - created_at
      - updated_at

Start here: the path by team size

TeamStart withThen addCost
Solo developerNative comments + SchemaSpy in DockerData dictionary query into a sheetFree
Small product teamNative comments + tbls in CIAzimutt for big schemasFree
Agency sharing with clientsdbdocs from db2dbmlPersonal Pro for private linksFree to $8/mo
Analytics team on dbtdbt Docs v2 or Catalogtbls for source databasesFree with dbt
Many sources, governance ownerDataedoLineage and data quality tiersFrom $18,000/yr

Documentation tells a teammate what total_cents means; it still doesn't answer "what was revenue by country last month?" for someone who can't write SQL. That is the gap AI for Database fills: connect your database read-only, ask in plain English, and get the answer with its SQL shown, then pin it to a self-refreshing dashboard. Try AI for Database free at aifordatabase.com; sample data is included. See how it works on PostgreSQL.

Frequently Asked Questions

What is database documentation?

Database documentation is a description of a database's tables, columns, relationships and business rules, usually a data dictionary plus an ER diagram. It lets someone who did not build the database understand and query it correctly.

What is the best free database documentation tool?

For most teams it is tbls if you use CI, because it can fail a build when a column has no description, and SchemaSpy if you want a full HTML site with diagrams in minutes. dbdocs is the easiest to share with people outside your team.

Is a data dictionary the same as database documentation?

A data dictionary is the core part of database documentation: the per-column list of names, types and meanings. Full documentation also covers relationships, ownership and business rules.

Where should database documentation be stored?

Store descriptions as comments inside the database and generated output in the same repository as the application code. That way schema changes and doc changes are reviewed together and never drift apart.

Can documentation be generated from an existing database?

Yes. tbls, SchemaSpy, SchemaCrawler and dbdocs (through db2dbml) all connect to a live database and generate documentation from its catalog, including any comments already stored on tables and columns.

How detailed should column descriptions be?

One sentence that says what the schema can't: units, allowed values and their meaning, the source system, and gotchas like soft deletes. Skip descriptions that only repeat the column name.

Ready to try AI for Database?

Query your database in plain English. No SQL required. Start free today.