Best Practices for Organizing Folders and Files in dbt Models
A deep dive into how to structure your `models/` directory in dbt for clarity, scalability, and performance.
In any dbt project, your models/ directory is the heart of your data transformation logic. As your project grows—from a handful of models to hundreds—organization matters.
A clean, consistent structure leads to:
- Better maintainability
- Faster onboarding for new teammates
- More scalable pipelines
This guide covers best practices for structuring your models/ folder—from naming to folders to modeling layers.
Start with a Layered Folder Structure
A best practice is to follow the staging → intermediate → marts model architecture.
Recommended Layout
models/
│
├── staging/
│ └── source\_system\_1/
│ └── stg\_orders.sql
│
├── intermediate/
│ └── int\_customer\_metrics.sql
│
├── marts/
│ ├── finance/
│ │ └── fct\_revenue.sql
│ ├── marketing/
│ │ └── dim\_customers.sql
Why It Works
staging/: One-to-one mapping to raw source tables, lightly cleaned and renamed.intermediate/: Join, filter, or transformstaging/logic into reusable business logic.marts/: Final curated tables for business consumers, including fact and dimension tables.
Each layer has a purpose and builds on the last—just like functions in code.
Follow Naming Conventions
Clear naming improves understanding and maintainability.
| Layer | Prefix | Example |
|---|---|---|
| Staging | stg_ | stg_customers.sql |
| Intermediate | int_ | int_customer_metrics.sql |
| Marts (Fact) | fct_ | fct_revenue.sql |
| Marts (Dimension) | dim_ | dim_customers.sql |
✅ Use lowercase and underscores
✅ Prefix with stg_, int_, dim_, or fct_
✅ Match the file name to the model name
Avoid generic names like final.sql or output_model.sql.
Organize by Domain or Source
Within each layer, organize models by source system or business domain.
Staging Example
models/
├── staging/
│ ├── stripe/
│ │ ├── stg\_stripe\_\_charges.sql
│ │ ├── stg\_stripe\_\_customers.sql
│ ├── hubspot/
│ │ ├── stg\_hubspot\_\_contacts.sql
Marts Example
models/
├── marts/
│ ├── sales/
│ │ ├── fct\_sales.sql
│ │ ├── dim\_salesperson.sql
│ ├── marketing/
│ │ ├── fct\_campaigns.sql
│ │ ├── dim\_channel.sql
This makes it easier to find and debug models related to a specific data source or business process.
Use dbt_project.yml to Configure Folders
You can define materialization defaults and tags for folders.
models:
my_project:
staging:
+materialized: view
+tags: [staging]
intermediate:
+materialized: ephemeral
+tags: [intermediate]
marts:
+materialized: table
+tags: [marts]This DRY pattern saves you from repeating {{ config(...) }} in every model.
Write One Model per File
One model = one .sql file. This keeps version control, testing, and debugging simple.
Avoid giant files with multiple SELECT statements. Instead, compose models like:
-- stg_orders.sql
-- int_orders_metrics.sql
-- fct_orders.sqlEach should:
- Contain a single
SELECTstatement - Be named to reflect the transformation
- Chain together logically
Co-Locate Tests and Documentation
Follow this structure:
models/
├── staging/
│ ├── stripe/
│ │ ├── stg_stripe__customers.sql
│ │ ├── stg_stripe__customers.yml <-- tests + docs
- Put schema-level tests (
unique,not_null,relationships) next to the model - Document descriptions, owners, and tags in the same YAML file
This helps with discoverability in dbt Docs.
Version and Archive Models (Optional)
For major data model changes:
models/
├── archive/
│ ├── fct_orders_v1.sql
├── marts/
│ ├── sales/
│ │ ├── fct_orders_v2.sql
- You can version models (
_v1,_v2) while transitioning consumers. - Move old models to
/archiveto retain lineage for audit/history.
Keep It Clean
A few additional tips:
- Avoid clutter: Remove deprecated models.
- Don’t over-nest folders: Keep it 2-3 levels deep.
- Group by purpose, not by arbitrary tags.
Best Practices
| Practice | Description |
|---|---|
✅ Use staging/, intermediate/, and marts/ layers | Clear logical separation |
| ✅ Follow naming conventions | stg_, int_, dim_, fct_ |
| ✅ Organize by domain or source | Easy navigation and debugging |
| ✅ One model per file | Simple Git diffs and tests |
| ✅ Add schema YAML next to model | Local tests + documentation |
✅ Configure folders in dbt_project.yml | DRY and centralized settings |
| ✅ Archive deprecated versions | Safe transitions |
| ✅ Avoid unnecessary nesting | Keep folder depth minimal |
A messy models/ folder slows down everyone. A clean structure accelerates everything—from onboarding to deployment.
Treat your dbt models like application code. Structure, name, and document them with care. Your future self—and your teammates—will thank you.