dbt Variables in Jinja

Variables in dbt let you pass values into your models at run time without hardcoding them in SQL. You define variables in configuration files or pass them on the command line. Your models read them using the var() function. Variables make models flexible and reusable across different time ranges, environments, and scenarios.

Defining Variables in dbt_project.yml

The most common place to define project-wide variables is dbt_project.yml:

# dbt_project.yml
vars:
  start_date: '2024-01-01'
  end_date: '2024-12-31'
  minimum_order_amount: 10
  exclude_test_accounts: true

Using Variables in Models

Use the var() function inside any model, macro, or test to read a variable value:

-- models/fct_orders.sql
select
    order_id,
    order_date,
    amount_dollars
from {{ ref('stg_orders') }}
where order_date between '{{ var("start_date") }}' and '{{ var("end_date") }}'
  and amount_dollars >= {{ var("minimum_order_amount") }}
  {% if var("exclude_test_accounts") %}
    and customer_id not in (select customer_id from {{ ref('test_accounts') }})
  {% endif %}

Providing a Default Value

The second argument to var() is a default value used when the variable is not defined:

{{ var('start_date', '2020-01-01') }}
-- Returns '2020-01-01' if start_date is not set anywhere

Overriding Variables at Run Time

Pass variables on the command line using the --vars flag. Command-line variables override values in dbt_project.yml:

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

# Multiple variables
dbt run --vars '{"start_date": "2025-01-01", "end_date": "2025-03-31", "minimum_order_amount": 50}'

Variable Priority Order

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

Practical Use Case: Date-Partitioned Backfill

Suppose you need to reprocess orders for a specific month. Without variables, you modify the SQL file, run it, then revert the change. With variables:

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

select
    date_trunc('month', order_date)   as revenue_month,
    sum(amount_dollars)               as total_revenue,
    count(distinct order_id)          as order_count
from {{ ref('stg_orders') }}
where order_date between '{{ var("start_date") }}' and '{{ var("end_date") }}'
group by 1
# Normal monthly run (uses dbt_project.yml defaults)
dbt run --select fct_monthly_revenue

# Backfill March 2024 specifically
dbt run --select fct_monthly_revenue \
    --vars '{"start_date": "2024-03-01", "end_date": "2024-03-31"}'

Environment-Specific Variables

Variables can hold different values per environment target. Define them nested under target names:

# dbt_project.yml
vars:
  # These apply to all targets
  minimum_order_amount: 10

# In profiles.yml, use target name to switch behavior
# Then in models read target.name:
-- In a model
{% if target.name == 'prod' %}
    where is_test_account = false
{% endif %}

Using Variables in Macros

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

Variable Naming Conventions

Good variable names:
  start_date          ← snake_case, descriptive
  minimum_order_value ← clear meaning
  exclude_cancelled   ← boolean names start with is_ or exclude_/include_

Avoid:
  dt                  ← too short
  var1                ← meaningless
  StartDate           ← inconsistent casing

Common Variable Patterns

Pattern             Example
-----------         -------
Date window         start_date, end_date
Threshold value     min_revenue, max_rows
Feature flag        enable_new_logic: true/false
Environment flag    is_dev: true/false
List of values      excluded_regions: ['APAC', 'EMEA']

Leave a Comment

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