Metacenta

Public dbt benchmark · 3 November 2026

How 227 public dbt projects measure up

We ran Metacenta's review engine over 227 public dbt projects on GitHub, each with at least 10 models (the median has 29). Most gaps are common, and a few are near universal: 93% have a source with no freshness check, and 88% have models with no tests at all. The full table and a CSV are below.

93%
Have a source with no freshness check
189 of 203 projects with sources
88%
Have models with no tests
median project: 44% of models untested
79%
Have undocumented models
median project: 39% of models
74%
Test a model without asserting its grain
no uniqueness test on a tested model

What the numbers say

  • Freshness is the most common gap. 93% of projects that declare sources leave at least one without a freshness threshold, so stale data reaches every model downstream with no warning. See Sources have a freshness threshold.
  • Untested models are the norm. 88% of projects have a model with no test, and in the median project 44% of models have none. See Models have at least one test.
  • Grain is rarely asserted. In 74% of projects with tests, at least one tested model has no uniqueness test, so nothing checks that it holds one row per key. See Tested models assert their grain (a uniqueness test).
  • select * is in half of projects. 50% use it in at least one model, so an upstream column change flows through unannounced. See Models select explicit columns.
  • Some things almost never go wrong. No project had a dependency cycle (0 of 227), because dbt refuses to parse one. A check that never fires here is a sign the engine isn't inventing problems.

Every check

The table lists each check that at least 50 projects could be evaluated on. Each row names what good looks like. "Projects falling short" is the share of projects with at least one model (or source) that doesn't meet it. "Median share flagged" is, for the median project, the share of its models (or sources) that don't. Download the CSV. 10 checks are left out because fewer than 50 projects used the feature they test (for example exposures, contracts or semantic models).

What good looks likeProjects falling shortMedian share flaggedProjects evaluated
Sources have a freshness threshold93%100%203
Models have at least one test88%44%227
Models declare their columns81%33%212
Core models describe every column79%100%138
Models carry a description79%39%227
Core models declare their grain77%30%138
Tested models assert their grain (a uniqueness test)74%22%199
Declared columns carry descriptions69%67%205
Sources carry a description52%9%203
Models select explicit columns50%0%227
Each source is read through one model43%0%203
Each source group carries a description43%0%203
Tested models assert key columns are populated42%0%199
A model is not joined back onto its own descendant41%0%227
Core models with several dates say which is which36%0%58
A model does not mix refs and raw sources36%0%203
A model joins at most one raw source33%0%203
Layer naming is applied consistently29%0%164
Model bodies stay readable28%0%227
Tests are declared beside the models they test22%0%179
Sources are read through staging, not directly by marts19%0%134
Every model declares where its data comes from19%0%227
Staging models read sources, not each other19%0%155
Incremental models declare a unique key19%0%118
Lineage depth stays workable14%0%227
Models reach inputs through ref() / source()11%0%227
Configured freshness checks can actually run9%0%53
No model is a single point of failure9%0%227
No two models hold identical logic4%0%227
Each warehouse relation is declared as a source once3%0%203
Staging models do not read transformed models2%0%155
The model DAG is acyclic0%0%227

Share of 227 public dbt projects that fall short of each check at least once

Frequently asked questions

Where do the projects come from?

GitHub code search for dbt_project.yml. We found 554 distinct projects with at least 20 model files and counted copies of the same demo once. We ran dbt parse on each with dbt-core 1.10.23, against a profile that never connects to a warehouse. 373 parsed; the rest needed credentials, environment variables or private packages and were left out rather than patched. Of those, 227 have at least 10 models in their own package. We name no repository.

How representative is this?

Public repositories lean towards portfolio, course and demo projects, and away from large production estates, which are almost always private. Treat these as rates for public dbt work, not for the industry. For most checks the rates are similar for projects of 10–24 and 25–99 models, which suggests the gaps aren't just a beginner effect. select * is the clearest exception: it's more common in the larger projects.

Which checks are included?

Only the checks a manifest alone can answer, out of 113 in the current suite. Checks that need run results, the catalog or warehouse query history aren't included, because public repositories don't publish those.

Can I reuse the data?

Yes. The CSV is free to reuse with a link back to this page.