An ephemeral model in dbt is a transient SQL transformation that never materializes as a table or view; instead, its compiled SQL is inlined into downstream models at run-time, resulting in zero footprint in the warehouse.
An ephemeral model in dbt is a lightweight transformation that exists only during compilation. Rather than persisting its results as a table or view, dbt injects ("inlines") the model’s SQL into every downstream model that references it. This keeps your warehouse lean, speeds up DAG execution, and eliminates extra permission work—at the cost of re-computing the subquery each time it’s used.
dbt (data build tool) supports four core materializations—table
, view
, incremental
, and ephemeral
. While the first three create persistent objects in your data warehouse, the ephemeral materialization is non-persistent. The compiled SQL from an ephemeral model is inserted as a CTE or subquery into every model that calls ref()
on it. As a result, no physical object is created, and the warehouse stores zero bytes for that transformation.
During dbt run
or dbt compile
:
materialized: ephemeral
.ref('my_ephemeral_model')
, dbt replaces that reference with the full SQL of the ephemeral model, wrapped as a Common Table Expression (CTE).CREATE TABLE/VIEW
, the warehouse sees only the outer model’s DDL.The result is a single warehouse query per non-ephemeral model, no matter how many ephemerals contribute inside.
Add a new SQL file in your models/
directory—for example, models/staging/stg_page_views_ephemeral.sql
.
-- models/staging/stg_page_views_ephemeral.sql
{{ config(materialized = 'ephemeral') }}
SELECT
user_id,
page_url,
event_timestamp
FROM {{ ref('raw_page_views') }}
WHERE event_name = 'page_view';
-- models/marts/fct_sessions.sql
WITH page_views AS (
SELECT *
FROM {{ ref('stg_page_views_ephemeral') }}
),
...
$ dbt run --select fct_sessions
Inspect the compiled SQL in target/compiled
; you’ll see the CTE page_views
contains the raw SQL from the ephemeral model.
stg_
or suffix _ephemeral
to convey non-persistence.table
or incremental
.--debug
and warehouse query logs to ensure inlined SQL isn’t causing redundant scans.materialized: table
or incremental
.Suppose you need to sessionize web events. You can:
stg_page_views_ephemeral
that filters raw events.stg_sessionize_ephemeral
that applies window functions over those views.fct_sessions
as a table
. The two staging layers never touch the warehouse.Below is a minimal, end-to-end example you can copy into a dbt project.
-- models/staging/stg_clicks_ephemeral.sql
{{ config(materialized = 'ephemeral') }}
SELECT *
FROM {{ source('app', 'events') }}
WHERE event_type = 'click';
-- models/staging/stg_purchases_ephemeral.sql
{{ config(materialized = 'ephemeral') }}
SELECT *
FROM {{ source('app', 'events') }}
WHERE event_type = 'purchase';
-- models/marts/fct_user_activity.sql
{{ config(materialized = 'table') }}
WITH clicks AS (
SELECT * FROM {{ ref('stg_clicks_ephemeral') }}
),
purchases AS (
SELECT * FROM {{ ref('stg_purchases_ephemeral') }}
)
SELECT
user_id,
COUNT(clicks.*) AS click_cnt,
COUNT(purchases.*) AS purchase_cnt
FROM clicks
LEFT JOIN purchases USING (user_id)
GROUP BY 1;
You’ll end up with a single persisted table (fct_user_activity
) and no intermediate objects.
Because Galaxy is a modern SQL editor with contextual AI, you can author .sql
model files for dbt locally, validate them against your warehouse, and leverage Galaxy’s AI copilot to refactor or optimize inlined SQL swiftly. The desktop app’s version control-friendly environment makes it particularly well-suited for iterating on ephemeral transformations that need rapid feedback but don’t require schema changes in the warehouse.
As data pipelines scale, the explosion of intermediate tables can slow down development, inflate storage costs, and complicate governance. Ephemeral models give data engineers a lever to keep DAGs modular without polluting the warehouse, enabling faster iterations and cheaper, more maintainable analytics layers.
No data is ever persisted. The SQL is inlined into downstream queries, so the warehouse only stores results for the outer model(s).
Use ephemerals for lightweight, rarely reused logic where reducing warehouse clutter outweighs the cost of recomputation. If performance degrades or multiple models reuse the same logic, switch to a view or table.
They generally speed up runs by avoiding table creation, but if the inlined SQL is heavy or reused widely, total query time can rise. Monitor warehouse execution plans to decide.
Yes. Galaxy’s desktop SQL editor lets you create and edit dbt model files locally, run them against your warehouse, and use the AI copilot to refactor SQL—all without leaving the IDE.