100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Documentation with dbt docs

dbt turns descriptions in your YAML files and standalone doc blocks into a browsable, auto-generated documentation site with an interactive lineage graph.

Testing & DocumentationBeginner8 min readJul 10, 2026
Analogies

Describing Models and Columns

The simplest way to document a model is a description field in schema.yml at both the model level and the column level, and these descriptions render as plain text or Markdown in the generated docs site. This turns tribal knowledge — like why a column called is_valid_order actually excludes test accounts, not just cancelled orders — into something every analyst can discover without pinging the person who wrote the model.

🏏

Cricket analogy: This is like a scorecard footnote explaining that a player's 'retired hurt' status doesn't count against the bowling figures the way a normal dismissal would — a detail a casual reader would otherwise miss entirely.

yaml
# models/marts/schema.yml
models:
  - name: fct_orders
    description: "One row per completed order. Excludes test accounts flagged in stg_customers."
    columns:
      - name: order_id
        description: "Primary key. Surrogate key generated from the source system's order UUID."
      - name: is_valid_order
        description: "True for real customer orders; false for orders placed by internal QA/test accounts, regardless of order status."

Doc Blocks for Longer, Reusable Descriptions

For descriptions that are long, reused across multiple models, or need Markdown formatting like bullet points and links, write a doc block instead: a {% docs some_name %} ... {% enddocs %} snippet in a .md file anywhere under models/, then reference it in schema.yml with {{ doc('some_name') }}. This avoids duplicating a lengthy explanation, like the full definition of 'active customer', across every column that needs it.

🏏

Cricket analogy: This is like a cricket board maintaining one official glossary entry for 'follow-on' that every match report links to, rather than each commentator re-explaining the rule from scratch every time.

markdown
{# models/marts/docs.md #}
{% docs active_customer %}
A customer is considered **active** if they have placed at least one
order in the trailing 90 days, based on `fct_orders.order_date`.
This excludes returned-only customers whose net order value is $0.
{% enddocs %}

Generating and Browsing the Docs Site

Running dbt docs generate compiles a manifest.json and catalog.json — the manifest captures your project's models, tests, macros, and their relationships from parsed source code, while the catalog captures actual column types and table stats pulled live from the warehouse's information schema. dbt docs serve then spins up a local static site reading those two files, giving you a searchable interface with every model's description, columns, compiled SQL, and an interactive DAG showing upstream sources and downstream consumers.

🏏

Cricket analogy: This is like a broadcaster's graphics team combining pre-match player profiles (known in advance) with live ball-by-ball data (pulled during the match) into one unified on-screen stats package for viewers.

The DAG view in dbt docs is one of the fastest ways to onboard a new analyst — clicking any node shows its full lineage, so they can trace a suspicious number in a dashboard all the way back to the raw source table without reading a single line of SQL first.

Organizing Docs with Tags and Groups

As a project grows past a few dozen models, plain descriptions aren't enough to navigate the docs site — tags (arbitrary labels like 'finance' or 'pii') and groups (formal ownership boundaries with defined access rules) let you filter and organize models in both the DAG and the model listing. meta fields go further, attaching arbitrary structured key-value data, like an owning team's Slack channel, that downstream tooling or custom docs templates can read.

🏏

Cricket analogy: This is like organizing a franchise's player database with tags such as 'overseas' or 'uncapped' alongside formal squad groupings like 'playing XI' versus 'reserves', so selectors can filter quickly.

The docs site reflects whatever was true the last time dbt docs generate ran — it is not live. If you change a model's SQL or description without regenerating, the site will silently show stale compiled SQL and column info, which is a common source of confusion in CI-driven docs deployments.

  • Model- and column-level description fields in schema.yml render directly in the generated docs site.
  • Doc blocks ({% docs %}...{% enddocs %} in .md files) let you write long, Markdown-formatted, reusable descriptions.
  • dbt docs generate builds manifest.json (parsed project structure) and catalog.json (live warehouse metadata).
  • dbt docs serve hosts a local static site with search, column docs, compiled SQL, and an interactive lineage DAG.
  • The DAG view is a fast way to trace any model's full upstream and downstream lineage.
  • tags, groups, and meta fields organize and filter large projects beyond plain text descriptions.
  • The docs site is a static snapshot — always regenerate after model or description changes to avoid stale docs.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#DbtDataBuildToolStudyNotes#DocumentationWithDbtDocs#Documentation#Dbt#Docs#Describing#StudyNotes#SkillVeris#ExamPrep