π What is custom_temp_schema
in dbt?
When dbt runs models that require intermediate or temporary tables, it needs a place (schema) to store them.
By default, these go into the same schema as the final models β which can clutter production schemas during development or testing.
β
custom_temp_schema
lets you control where dbt creates temporary tables during execution:
- Keeps temp tables out of your production schema.
- Helps you isolate developer activity.
- Can be set globally, per environment, or per model.
π¦ Example: Setting custom_temp_schema
in dbt_project.yml
# dbt_project.yml
name: my_project
version: 1.0.0
profile: my_profile
# Default behavior for all models
models:
my_project:
+schema: analytics # Final output schema for models
+custom_temp_schema: dbt_temp # Temp tables go here during execution
π§± Result: Schema resolution
Object Type | Target Schema |
---|---|
Final models | analytics |
Temp/intermediate | dbt_temp |
This applies to models that use intermediate relations (e.g., ephemeral models or materializations that build temp objects first).
π§ͺ Example: Used during ephemeral joins or CTE generation
Imagine this dbt model:
-- models/customer_orders.sql
select
customer_id,
count(*) as order_count
from {{ ref('stg_orders') }}
group by customer_id
If stg_orders
is an ephemeral model, dbt may create a temporary CTE or even a temp table (depending on the adapter) to resolve dependencies.
With custom_temp_schema: dbt_temp
, that object will not clutter analytics
β it lands in dbt_temp
.
π― Overriding at the model level
You can override custom_temp_schema
for specific models too:
-- models/experiments/my_experimental_model.sql
{{ config(
materialized='table',
custom_temp_schema='experimental_temp'
) }}
select ...
This modelβs temporary/intermediate tables will go to experimental_temp
, even if the rest of the project uses dbt_temp
.
π§Ό Summary
Feature | Benefit |
---|---|
custom_temp_schema | Defines where dbt stores temp/intermediate tables |
π§ͺ Used in dev/testing | Avoids polluting production schemas |
π§ Configurable scope | Can be set at project, folder, or model level |
π§Ή Keeps things clean | Helps maintain separation of dev vs prod assets |
β In dbt, βtemporary tablesβ can mean three things:
Concept | Description |
---|---|
CTEs (Common Table Expressions) | Inline temporary result sets (e.g. WITH ... ) β no table is created in the database. |
Temporary physical tables | Real tables created in the database but automatically dropped after the session ends. Only some databases support this. |
Intermediate tables in a custom schema | Used by dbt internally during materializations (e.g., staging, rebuilding models). These are not marked as temporary, but they are intermediate. |
π§± Letβs break them down:
πΉ 1. CTEs (Common Table Expressions)
WITH orders_per_customer AS (
SELECT customer_id, COUNT(*) as order_count
FROM orders
GROUP BY customer_id
)
SELECT *
FROM orders_per_customer
- β Defined inline
- π§Ή Automatically discarded after the query ends
- β Not visible in the database catalog
- β
Used heavily when you use
materialized='ephemeral'
in dbt
β‘οΈ This is NOT affected by custom_temp_schema
, because no table is created.
πΉ 2. Temporary Physical Tables
Some databases (e.g. PostgreSQL, Snowflake, Databricks) support real temporary tables like:
CREATE TEMPORARY TABLE my_temp_table AS
SELECT ...
- β Physically exists but auto-deleted when the session ends
- β Often used by dbt internally during custom materializations
- β
Could be created in the schema defined by
custom_temp_schema
- β Some databases don’t support temp tables the same way (e.g., BigQuery treats them differently)
β‘οΈ This can be affected by custom_temp_schema
, depending on how the adapter and materialization work.
πΉ 3. Intermediate Tables Created by dbt in Custom Temp Schemas
Even if a table is not a true TEMP TABLE
, dbt might simulate temporary behavior by:
- Creating an intermediate table (e.g.
_tmp123_my_model
) - Placing it in a custom schema (like
dbt_temp
) - Then swapping it into place after the build completes
# dbt_project.yml
models:
my_project:
+custom_temp_schema: dbt_temp
These are regular tables, but considered temporary in purpose (for build process only), not in SQL semantics.
π§ͺ Example: What Happens When You Use custom_temp_schema
Assume:
- Final model is
analytics.final_sales
- You set
+custom_temp_schema: dbt_temp
During execution:
- dbt creates an intermediate table like
dbt_temp.final_sales__dbt_tmp
- Once the build is successful, it renames/moves this table to
analytics.final_sales
- The temp table is then dropped automatically by dbt
β This is dbt’s way of isolating temp/intermediate artifacts during builds.
β Summary Table
Type of Temp Structure | Created In Database? | Affected by custom_temp_schema ? | Auto-Cleanup? | Use Case |
---|---|---|---|---|
CTE (WITH clause) | β No | β No | β Yes | Ephemeral logic |
Temporary Table (TEMP ) | β Yes (if supported) | β Yes (depends on adapter) | β Yes (session ends) | Internal queries, staging |
Intermediate dbt Table | β Yes | β Yes | β Yes (dbt deletes or swaps) | Rebuilds, staging, concurrency handling |