dbt Project Variables

Project variables let you define reusable values in dbt_project.yml and reference them inside your SQL models, macros, and tests. Variables make your project more flexible by separating configuration from logic. You define a variable once and change its value without touching any SQL files.

Defining Variables

Define project variables in the vars block of dbt_project.yml:

# dbt_project.yml
vars:
  # Date range for analysis
  start_date: '2024-01-01'
  end_date: '2024-12-31'

  # Business thresholds
  minimum_order_amount: 10
  high_value_order_threshold: 500
  refund_lookback_days: 90

  # Feature flags
  include_test_orders: false
  enable_cohort_analysis: true

  # Lists
  active_regions: ['US', 'CA', 'GB', 'AU']
  excluded_channels: ['internal', 'test']

Reading Variables in Models

Use the var() function anywhere Jinja is supported:

-- models/fct_orders.sql
{{ config(materialized='table') }}

select
    order_id,
    customer_id,
    order_date,
    amount_dollars,
    case
        when amount_dollars >= {{ var('high_value_order_threshold') }}
        then 'high_value'
        else 'standard'
    end as order_tier
from {{ ref('stg_orders') }}
where order_date between '{{ var("start_date") }}' and '{{ var("end_date") }}'
  and amount_dollars >= {{ var('minimum_order_amount') }}
  {% if not var('include_test_orders') %}
    and is_test_order = false
  {% endif %}

Default Values in var()

The second argument is the default, returned when the variable is not defined anywhere:

{{ var('start_date', '2020-01-01') }}
-- Returns '2020-01-01' if start_date is not in dbt_project.yml

{{ var('custom_schema', none) }}
-- Returns none (Python None → SQL NULL context) if variable is missing

Overriding Variables at Run Time

Pass --vars on the command line to override any variable for that run:

# Override one variable
dbt run --vars '{"start_date": "2025-01-01"}'

# Override multiple variables
dbt run --vars '{"start_date": "2025-Q1", "end_date": "2025-03-31", "include_test_orders": true}'

# Override to backfill a specific period
dbt run --select fct_orders \
    --vars '{"start_date": "2024-06-01", "end_date": "2024-06-30"}'

Variable Priority

Highest → command-line --vars flag
        → dbt_project.yml vars block
Lowest  → var() second argument (default value)

Using Variables in Macros

-- macros/get_date_filter.sql
{% macro get_date_filter(date_column='order_date') %}
    {{ date_column }} between
        '{{ var("start_date") }}'
    and '{{ var("end_date") }}'
{% endmacro %}
-- In any model
select *
from {{ ref('stg_orders') }}
where {{ get_date_filter() }}

-- With a custom column name
where {{ get_date_filter('ship_date') }}

Using Variables in Tests

# schema.yml — use variables in accepted_values via Jinja
models:
  - name: stg_sessions
    columns:
      - name: region
        tests:
          - accepted_values:
              values: "{{ var('active_regions') }}"

Configuring Variables per Environment

Variables in dbt_project.yml apply to all environments. To use different values per environment, combine variables with target-specific logic:

-- In a model
{% if target.name == 'prod' %}
    {% set lookback = var('refund_lookback_days') %}
{% else %}
    {% set lookback = 7 %}  ← shorter window in dev to speed up runs
{% endif %}

select * from {{ ref('stg_refunds') }}
where refund_date >= dateadd(day, -{{ lookback }}, current_date)

Documenting Variables

Document all project variables in a comment block in dbt_project.yml so teammates understand their purpose:

vars:
  # start_date: beginning of the analysis period (YYYY-MM-DD)
  # Used in: fct_orders, fct_revenue, fct_sessions
  start_date: '2024-01-01'

  # minimum_order_amount: orders below this USD value are excluded
  # Used in: fct_orders, fct_revenue
  minimum_order_amount: 10

  # include_test_orders: set to true in dev to include test data
  # Default: false (production excludes test orders)
  include_test_orders: false

Variables vs Environment Variables

Feature              Project Variables (var())    Env Variables (env_var())
-----------          -------------------------    -------------------------
Store secrets?       No                           Yes
Visible in logs?     Yes                          No (values hidden)
Change per run?      Yes (--vars flag)            Yes (set in shell/CI)
Change per env?      With target.name logic       Yes (set per environment)
Best for:            Business logic values        Credentials, schema names

Leave a Comment

Your email address will not be published. Required fields are marked *