DBT in Action: Build the Marts Layer That Connects Your Data to the Business
Welcome back, dear readers! And welcome to the third and final post in this series about the wonderful world of DBT. In previous installments, we explored in depth how to structure data in the initial layers of a DBT project: staging models to unify the data and intermediate models that apply business logic to transform that data.
In this post, we’ll look at the final stage of those transformations: the marts layer, where data is available for consumption, ready for the business, and useful for advanced analytics or BI tools.
What Is a Mart in DBT?
A mart is the final, curated layer of our data warehouse, represented like the rest of our project components by a .sql file containing a column selection. Its purpose is to expose clean, reliable, business-oriented datasets that analysts and business users can consume directly.
Unlike staging and intermediate models that focus on data integrity and logical transformations, marts focus on usability.
That’s why they represent the culmination of all the modeling work we’ve done so far. It’s where our transformations stop being just data structure decisions and become supports for decision-making, performance tracking, risk monitoring, or business results analysis.
Marts are typically denormalized: they consolidate information from multiple intermediates into a single, larger table. Each record represents a clear business entity (like a loan, customer, or transaction) enriched with KPIs or aggregated metrics, ready to be visualized in a BI dashboard or consumed by a machine learning model.
This is why a well-designed mart often looks more like a business document than a technical artifact. Someone without SQL knowledge probably can’t deeply interpret an intermediate model, but a mart should be clear and understandable. Column names should be readable and obvious (total_disbursed_amount instead of td_amt), and the resulting table should align with how the business thinks about its operations. In essence, marts take complex data pipelines and turn them into accessible, reliable datasets.
Let’s look at a simple mart example:
This mart joins several intermediate data sources to produce a final, unified view of loan performance for a hypothetical fintech. The result is a clean, organized dataset ready for analytics that can feed financial reports, risk analysis, and operations dashboards.
From Raw to KPI: The Data Lineage Journey
The mart layer is the natural conclusion of DBT’s model hierarchy, which looks like this:
Raw → Staging → Intermediate → Mart
Each step depends on the quality of the previous one. Staging handles essential transformations like column cleanup, data type casting, and duplicate record removal. Intermediate models add business logic, like calculations of key operational KPIs. And finally, the mart layer unifies everything and makes it available.
In DBT, we can visualize this lineage of sources and transformations using the dbt docs generate command. When executed, you’ll see something similar to:
raw_customer_data → stg_customers → int_loans_data → mart_loans
This visual traceability, highly simplified for this example, is one of DBT’s most powerful features. It ensures that every business metric can be traced end to end, from its source to its mart, giving us confidence and transparency in the analysis process.
What Makes a Good Mart?
Mart design requires special attention to things like naming, schema organization, and test definitions. These are what separate a functional model from one that’s sustainable and production-ready.
From a naming perspective, marts should be easily identifiable, so using suffixes or prefixes like mart or mart helps distinguish them clearly. Additionally, they should contain something in their name that indicates their business use. A good name might be mart_loan_performance.sql.
Schema organization is equally important. Keeping marts in a dedicated schema (usually called, you guessed it, marts) helps maintain organization of pipeline components within our data warehouse. This also simplifies permission assignment, since marts are typically the only schema exposed to BI analysts. In our dbt_project.yml (which we’ve already seen in previous posts), this can be configured like so:
Data quality should always be top of mind, especially when working with complex transformations. That’s why tests are a fundamental component of any mature, well-designed DBT project. To that end, we can add tags to our marts in the project .yaml to help distinguish which marts are critical for each business operation:
We can even define specific tests that ensure data quality and that the transformations we’ve built (or will build in the future) continue meeting our data standards, with the goal of avoiding costly errors or bad business decisions.
Performance, Dialed In
Since marts handle aggregated or historical data, optimizing process performance is critical to maintaining efficiency and scalability as our data volume grows. Fortunately, DBT offers several materialization options that determine how our models are built and stored.
For example, for small to medium marts, table materialization is usually more than enough. It recreates the table each time, guaranteeing final result consistency at the cost of slightly longer build times. In contrast, for large datasets, incremental logic is preferred, as it only processes new or updated data on each run.
A typical incremental mart configuration looks like this:
If we’re working with data warehouses that support it (like Google BigQuery or Amazon Redshift), we can optimize even further through partitioning and clustering strategies:
These types of configurations can significantly improve query performance, especially for dashboards or analytical queries that run regularly. Partitioning helps isolate recent data for faster incremental updates, while clustering improves filtering and join performance.
What About the Docs?
Finally, we arrive at the crowning piece of any project… documentation! Without documentation, anyone trying to understand the project or just looking up a general question about its structure is going to have a hard time.
In DBT, documentation is what transforms a mart from a usable table into a data asset shared across the entire organization. Fortunately, DBT also makes the documentation process much easier, since it’s embedded directly in the project. This ensures that business context is delivered alongside technical definitions.
What do I mean by this? Each individual mart should have a schema.yml file that describes its purpose, the columns it contains, and key metrics. For example:
This is already very useful, but we can go a step further: once this file is defined and the documentation is in place, we can generate an interactive, navigable site using the following commands:
dbt docs generate
dbt docs serve
This, as if by magic (well, code), creates a data catalog with lineage graphs, column descriptions, and relationships. It goes without saying that this is an invaluable resource for analysts, data engineers, and business users alike: it not only helps understand what each mart contains, but also shows how we arrived at the final numbers exposed in our marts.
That’s a Wrap…
These were three posts with a lot of conceptual and technical depth, demos, and code. Learning a framework as flexible as DBT belongs in any data developer’s toolkit today: it’s plain SQL, readable, maintainable, and scalable, and a fundamental tool in the modern data stack.