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.

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 stages

  • Always give defaults in dbt_project.yml so local runs don’t break

  • Use 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?