The full answer
Match the materialization to how each model is used. Views for light models that only rename and cast, since they cost nothing to build; tables for models that BI tools query or many models reuse; incremental for large event tables where rebuilding all of history each night is the waste; ephemeral for small reusable steps that need no object in the warehouse; a materialized view where the database can keep a result fresh on its own. Here, the 2-billion-row events model should be incremental, the staging models views, and the marts the dashboard reads tables.
1. The 5 built-in materializations
| Materialization | Built as | Good | Costs |
|---|---|---|---|
| view | create view as | No storage, always current | Slow when it does heavy work or stacks on other views |
| table | create table as, every run | Fast to query | Rebuilt in full every run |
| incremental | Insert or merge only new rows | Fast runs on big tables | More configuration, a full refresh now and then |
| ephemeral | A CTE inside the models that use it | Keeps the warehouse tidy | Cannot be queried directly |
| materialized view | The database's materialized view | Table speed, refreshed by the database | Depends on what the platform supports |
dbt's own advice is to start with views and change only when performance asks for it, and not to start with incremental.
2. Applying it to the 3-hour run
# dbt_project.yml
models:
shop:
staging:
+materialized: view
marts:
+materialized: table
-- models/marts/fct_events.sql
{{ config(materialized='incremental', unique_key='event_id') }}
select * from {{ ref('stg_events') }}
{% if is_incremental() %}
where event_time >= (select max(event_time) from {{ this }})
{% endif %}
- The staging models were rebuilt as tables each night but only rename columns: as views they cost nothing to build.
- The events model now processes a night's rows, not 2 billion.
- The marts stay tables, because the dashboard reads them all day.
3. How to decide on a model you have not seen
- Who reads it? A person or a BI tool, often: table. Only other models: view or ephemeral.
- How heavy is it? Renames and casts: view. Joins and aggregates over large data: table or incremental.
- How big is it, and does it grow by appending? Large and append-mostly: incremental.
- Does the platform refresh materialized views well? Then that is an option for a result that must stay fresh.
4. Measure, then change
Read the run timings in run_results.json or the dbt platform to find the slowest models before changing anything; usually a handful of models take most of the 3 hours.
What interviewers want: the 5 materializations and their trade-offs, views by default, tables for what BI reads, incremental for large append-mostly models and not by default, ephemeral as a CTE, and choosing by who reads a model and how heavy it is.
Last updated 16 October 2026
Sources