Project and Environment Variables
Project and Environment variables allow you to parameterize logic in your dex project so it can behave differently depending on where or how it’s running. They’re most commonly used to avoid hardcoded values, toggle configurations between environments, and securely inject credentials or tokens using secrets.
These variables follow a familiar pattern used in templated analytics workflows and are evaluated at compile time, making them accessible inside models, macros, snapshots, seeds, and more.
Don’t confuse transformation variables with secrets stored in dex's Secrets Manager. Variables are used to control logic at compile time (like schema names or flags), while secrets are encrypted values (like passwords or tokens) used to securely configure external connections.
Where Variables Come From
Variables in dex are defined in two ways:
Project variables: Defined in the
dbt_project.yml
file. These are global to the entire dex project and apply across all environments.Environment variables: Defined in the dex UI, scoped to a specific environment (e.g.,
dev
,staging
,production
). These override project-level defaults and are evaluated first when resolving variables.
You can also mark any environment variable as a secret, ensuring it is encrypted and hidden after being saved.
How to Define Project Variables
Inside your project, you can define variables in dbt_project.yml
like this:
vars:
start_date: '2023-01-01'
schema_suffix: '_dev'
These variables are accessible anywhere in your models using the var()
function.
Using Variables in Your Models
You can access both project and environment variables using the var()
Jinja function:
select *
from raw.customers
where created_at >= '{{ var("start_date") }}'
You can also use them for logic in macros, seeds, snapshots, and materialization configs:
{% if var('schema_suffix') == '_prod' %}
-- production logic
{% else %}
-- dev logic
{% endif %}
Variables are evaluated at compile time, meaning they are rendered before your model or macro runs in the warehouse.
Precedence
When a variable with the same name is defined in both the project and the environment:
Environment variable wins — it will override the project-level default during execution.
This makes it easy to test safely in dev while preserving production configurations in place.
Example Use Case
Let’s say you want to limit row output in development but run full datasets in production:
Project-level
dbt_project.yml
:
vars:
row_limit: null
Environment override (dev):
Name: ROW_LIMIT
Value: 100
Scope: Environment
Environment: dev
Model logic:
select *
from {{ ref('orders') }}
{% if var('row_limit') %}
limit {{ var('row_limit') }}
{% endif %}
In dev, this model limits rows to 100. In production, it runs without a limit.
Best Practices
Use
var('...')
to make behavior configurable across projects or stagesAlways give defaults in
dbt_project.yml
so local runs don’t breakUse uppercase names with underscores for consistency (
SCHEMA_NAME
,LIMIT_ROWS
)Use secrets for anything sensitive (API tokens, passwords)
Document variable usage in your project README or
.yml
files
Last updated
Was this helpful?