Data Engineering  /  dbt

๐Ÿ”„ dbt โ€” Data Build Tool 60 guides ยท updated 2026

Analytics engineering with SQL โ€” models, tests, sources, and Jinja macros that turn raw warehouse tables into trustworthy, documented data products.

dbt docs generate: Producing Your Projectโ€™s Documentation Automatically

Documentation that lives in a separate wiki, disconnected from the actual code, goes stale within weeks โ€” someone renames a column, forgets to update the doc, and now the documentation is actively misleading rather than just incomplete. dbtโ€™s approach avoids this by generating documentation directly from the project itself: descriptions you write in YAML, combined with metadata dbt already tracks about every model, source, and column.


Running dbt docs generate

Terminal window
dbt docs generate

This produces two key JSON artifacts inside target/:

Together, these two files are what powers the interactive documentation site, covered operationally in dbt Docs Serve.


Where Documentation Content Actually Comes From

dbt doesnโ€™t invent descriptions โ€” every piece of documentation text comes from what youโ€™ve explicitly written in YAML files, attached to models, columns, and sources.

models/staging/_stg_orders.yml
models:
- name: stg_orders
description: "Cleaned, one-row-per-order staging model. Filters out internal test orders."
columns:
- name: order_id
description: "Primary key, unique per order."
- name: status
description: "Order lifecycle status: pending, shipped, delivered, cancelled, or returned."

Running dbt docs generate after adding these descriptions pulls them directly into the generated site โ€” thereโ€™s no separate documentation-writing step beyond what youโ€™ve already declared for testing and organizational purposes.


Documentation Blocks for Longer, Reusable Descriptions

For descriptions that are long, or reused across multiple models (a shared column meaning across several tables), a {% docs %} block keeps YAML files from becoming unwieldy.

{% docs order_status_description %}
Order lifecycle status. Possible values:
- `pending`: order placed, payment not yet confirmed
- `shipped`: payment confirmed, package has left the warehouse
- `delivered`: confirmed received by customer
- `cancelled`: order cancelled before shipment
- `returned`: customer-initiated return, refund processed
{% enddocs %}
columns:
- name: status
description: "{{ doc('order_status_description') }}"

This is worth doing whenever the same column meaning repeats across multiple models โ€” a single doc block reused via {{ doc(...) }} stays consistent everywhere itโ€™s referenced, rather than five slightly-drifting copies of similar but not identical text.


What Gets Captured Automatically vs. What You Have to Write

Captured automatically from project structureRequires explicit description
Dependency graph (which models reference which)What a model or column actually means
Materialization type (table, view, incremental)Business context and caveats
Column names and types (from catalog.json)Why a filter or transformation exists
Test coverage per columnKnown limitations or edge cases

This split matters โ€” dbt gives you the structural skeleton of documentation for free, but the actual, valuable context still requires someone to write it. A project with zero YAML descriptions still generates a lineage graph, but itโ€™s a graph of undocumented boxes.


Generating Docs as Part of a Scheduled Job

Since documentation is derived from the current state of the project, it needs to be regenerated after every meaningful change to stay accurate โ€” most teams run it as the final step of a production build.

Terminal window
dbt build
dbt docs generate

Running dbt docs generate without a preceding successful build still works, but catalog.json will only reflect whatever tables actually exist in the warehouse from the last successful build โ€” stale documentation isnโ€™t usually catastrophic here, but itโ€™s worth understanding that this command reflects the warehouseโ€™s actual current state, not necessarily your latest uncommitted local changes.


Hosting the Generated Site

dbt docs generate only produces the artifacts โ€” actually viewing them requires either dbt docs serve locally (covered next) or hosting the generated target/ directoryโ€™s static files somewhere accessible to your team, which is how dbt Cloudโ€™s hosted documentation feature and most self-hosted setups work in practice.

Terminal window
# Typical CI step: generate docs, then upload target/ to a static host
dbt docs generate
aws s3 sync target/ s3://internal-docs-bucket/dbt-docs/ --delete

Generating Docs Without a Live Warehouse Connection

catalog.json requires querying the warehouse for actual column metadata, but manifest.json โ€” the structural, dependency-graph portion of the documentation โ€” can be produced without any live connection at all, using --no-compile or by simply running dbt parse instead of a full dbt docs generate.

Terminal window
dbt parse

This is useful in constrained environments (a laptop without VPN access to the warehouse, for instance) where you still want to browse the projectโ€™s structure and lineage graph locally, accepting that column type and row-count information wonโ€™t be available until a full dbt docs generate runs against a live connection.

Common Mistakes

Never adding YAML descriptions and expecting useful documentation anyway. The generated site will show structure and lineage regardless, but without descriptions, itโ€™s a map with no labels โ€” technically complete, not actually useful to a new team member.

Regenerating docs infrequently. Stale documentation that shows a lineage graph from three model changes ago is actively worse than no documentation, since it looks authoritative while being wrong.

Writing the same column description five times instead of using {% docs %} blocks. This is the exact copy-paste problem macros solve for logic โ€” documentation benefits from the same reuse discipline.

Summary

ArtifactContains
manifest.jsonFull project structure, dependencies, configuration
catalog.jsonActual warehouse metadata โ€” columns, types, from built tables
YAML description: fieldsWhere all documentation text originates
{% docs %} blocksReusable, longer-form descriptions referenced via doc()

dbt docs generate turns documentation from a separate, drifting artifact into a byproduct of the project itself โ€” accurate exactly to the degree that the underlying YAML descriptions are actually kept up to date.