All skills
dbt-labs avatar

/working-with-dbt-mesh

@8908932 official
by dbt Labsdbt-labs/dbt-agent-skills729 stars
62

Use when changing a dbt model in a way that could break its consumers — renaming, removing, or retyping a column, or changing a model that downstream models, exposures, dashboards, or BI tools depend on — to judge whether the change is breaking and who it affects. Also use when versioning a model (model versions, latest_version, latest_version_pointer, deprecation_date, migration windows), enforcing contracts, setting access or groups, or doing multi-project dbt Mesh work (cross-project refs via dependencies.yml, disambiguating similarly-named models, splitting a monolith). Covers single- and multi-project, and planning or advising as well as implementing.

Use this Skill: https://skilld.dev/gh/dbt-labs/dbt-agent-skills/working-with-dbt-mesh

This session only. Nothing lands on disk.

referencesgroups-and-access.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Groups and Access Modifiers

Groups and access modifiers work together to organize models by team ownership and control which models can reference each other.

Groups

Groups represent domains of resources owned by a specific team. They make ownership explicit — when something breaks, you know who to contact.

Defining Groups

Groups can be defined in a standalone YAML file or alongside model definitions:

# models/_groups.yml (or any .yml file in your models directory)
groups:
  - name: finance
    owner:
      name: Firstname Lastname
      email: finance@jaffleshop.com
      slack: finance-data
      github: finance-data-team
  - name: product
    owner:
      email: product@jaffleshop.com
      github: product-data-team

Owner requirements: At least name or email is required. Other properties (slack, github) are optional.

Assigning Models to Groups

Three ways to assign a model to a group:

1. In model YAML (recommended for individual models):

models:
  - name: fct_orders
    config:
      group: finance

2. In dbt_project.yml (recommended for directory-level assignment):

# dbt_project.yml
models:
  my_project:
    marts:
      finance:
        +group: finance
      marketing:
        +group: marketing

3. In SQL config block:

-- models/marts/finance/fct_orders.sql
{{ config(group='finance') }}

select ...

What Can Be Grouped

Groups apply to: models, seeds, snapshots, tests, analyses, metrics, semantic models, and saved queries.

Access Modifiers

Access modifiers control which models can ref yours:

Access Who Can Reference Use Case
private Same group only Internal implementation details, rapidly changing models
protected Same project (or installed as a package) Standard intra-project models (this is the default)
public Any group, package, or project Stable APIs intended for cross-team or cross-project consumption

Configuring Access

Important: access is a config property and must be nested under config: in YAML property files. Placing it as a top-level model property breaks the Fusion engine. The same applies to group — always co-locate them under config:.

# ✅ CORRECT
models:
  - name: fct_orders
    config:
      group: finance
      access: public

# ❌ WRONG — breaks Fusion
models:
  - name: fct_orders
    access: public     # not under config:
    group: finance     # not under config:

In dbt_project.yml at the directory level, use the + prefix:

models:
  my_project:
    staging:
      +access: private
      +group: platform
    marts:
      +access: protected

Or in SQL:

{{ config(access='public', group='finance') }}

Access Rules

  • Default access is protected — all models in a project can reference each other regardless of group
  • private models trigger a DbtReferenceError if referenced from outside their group
  • public models are the only models visible to other projects via cross-project ref()
  • Ephemeral models cannot be public — attempting this causes a parsing error

Access and Contracts

Access and contracts are complementary:

Access Level Contract Recommended? Why
public Yes Consumers outside your project depend on schema stability
protected Optional Useful for high-criticality intra-project models
private No Internal models change frequently; contracts add friction

Practical Example: Multi-Team Project

# models/_groups.yml
groups:
  - name: finance
    owner:
      email: finance-data@company.com
  - name: marketing
    owner:
      email: marketing-data@company.com

# models/marts/finance/_finance_models.yml
models:
  - name: fct_revenue
    config:
      group: finance
      access: public       # Other projects can ref this
      contract:
        enforced: true
    columns:
      - name: revenue_id
        data_type: varchar
      - name: amount
        data_type: numeric(38, 2)
      - name: recorded_at
        data_type: timestamp_ntz

  - name: int_revenue_daily
    config:
      group: finance
      access: private       # Only finance group can ref this

# models/marts/marketing/_marketing_models.yml
models:
  - name: fct_campaigns
    config:
      group: marketing
      access: protected     # Same project can ref, other projects cannot

In this setup:

  • fct_revenue is available to anyone (public, contracted)
  • int_revenue_daily is only available within the finance group
  • fct_campaigns is available to all models in the same project but not to other projects
  • If fct_campaigns tries to ref('int_revenue_daily'), dbt raises a DbtReferenceError

Best Practices

  1. Start with private for new models and widen access only when there's a real consumer
  2. Always pair public with a contract — a public model without a contract is a liability
  3. Use directory-level group assignment in dbt_project.yml when your directory structure mirrors team ownership
  4. Keep groups aligned with team structure — a group should map to a real team that can respond to issues
  5. Don't create groups for one model — groups represent team boundaries, not individual model boundaries

Common Mistakes

Mistake Fix
Not assigning a group to private models private access requires a group — dbt errors without one
Making everything public Only public-ify models that are intentional cross-team APIs
Creating groups that don't map to real teams Groups need an owner who can respond when things break
Relying on protected (default) when private is more appropriate Be intentional — protected is permissive within the project
Expecting access to control database permissions Access modifiers are a dbt concept — manage database permissions separately
Placing access or group as top-level model properties in YAML Nest under config: — top-level placement breaks Fusion

Source: SKILL.md on GitHub

No alerts17d4 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides thorough documentation and architectural guidelines for managing data governance, versioning, contracts, and cross-project compilation boundaries within a dbt Mesh setup. No malicious code patterns, obfuscations, or credential exposures were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 8908932. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 4 months ago
user-invocable
false
metadata
{
  "author": "dbt-labs"
}
  • dbt
  • dbt-mesh
  • governance
  • cross-project-ref
  • contracts
  • access-modifiers
  • groups
  • versioning
  • multi-project

README badge

README badge for dbt-labs/dbt-agent-skills/working-with-dbt-mesh

Implements dbt Mesh governance features — model contracts, access modifiers, groups, and versioning — plus multi-project collaboration with cross-project refs and dependencies.yml. Use when setting up cross-project references between dbt projects, adding access controls and contracts to models, or splitting a monolithic dbt project into multiple mesh projects.

Generated from the current SKILL.md.

Does this skill work with dbt Cloud Standard or Free plans?
Cross-project refs require dbt Cloud Enterprise or Enterprise+. Intra-project governance features (groups, access modifiers, contracts, versioning) work on all plans.
Can I reference models marked as protected or private cross-project?
No. Only models with `access: public` can be referenced across projects. Coordinate with the upstream team to change the access level if you need a different model.
What happens if multiple upstream projects have models with the same name?
You must use the two-argument `ref()` syntax with the explicit project name: `ref('project_name', 'model_name')`. Single-argument `ref()` will fail or resolve to the wrong project.
Do I need contracts on all public models?
Contracts are strongly recommended for public models, especially those referenced cross-project or fed to exposures. Do not add contracts to staging models, ephemeral models, or models still in design flux.
What is the difference between contracts and data tests?
Contracts enforce column names and types at build-time before the model materializes. Data tests validate content and business rules post-build. Contracts are for shape guarantees; tests are for data quality.

Generated from the current SKILL.md. These answers refresh after source changes.