Skip to main content
Build models are data transformations that run during the build process (such as the sqrl build CLI command) and materialize their results in the Virtual Data Lake (VDL). They are used to create reusable data layers that can be referenced by other models. Build models can be written in SQL (DuckDB dialect) or Python, and are stored in the models/builds/ directory.

File structure

The logic of the build model can be written in SQL or Python. Optionally, the metadata of the build model (such as column descriptions) can be specified in a YAML file with the same name.

SQL build models

SQL build models use the DuckDB SQL dialect and support Jinja templating.

Example SQL model

models/builds/build_transactions.sql

Available Jinja variables

The following variables are available in SQL build models:

The ref() macro

The ref() macro is used to reference other models. It can reference:
  • Sources (with load_to_vdl: true or DuckDB connection type)
  • Seeds
  • Other build models

Python build models

Python build models define a main() function that receives a BuildModelArgs object and returns a Polars LazyFrame (or DataFrame).

Example Python model

models/builds/build_transactions.py

YAML configuration

An optional YAML file with the same name provides additional configuration for the model.
models/builds/build_transactions.yml

Configuration fields

string
default:""
A description of the model for documentation purposes.
string
default:"VIEW"
How the model is stored in the VDL. Options are TABLE or VIEW.
Python models are always materialized as tables regardless of this setting.
list[string]
default:"[]"
List of model names this build model depends on. Optional for SQL models (derived from ref() calls), but required for Python models.
list[object]
default:"[]"
Column metadata definitions as a list.

Materialization

Build models can be materialized as either tables or views in the VDL:
Python build models are always materialized as tables, regardless of the materialization setting. This is because DuckDB only supports view definitions in SQL, not Python.

Best practices

  1. Use descriptive names: Prefix build model names with build_ to distinguish them from other model types.
  2. Declare dependencies explicitly: Even though SQL models can auto-detect dependencies via ref(), explicitly listing them in YAML helps with documentation.
  3. Use pass_through for inherited columns: When a column passes through unchanged from an upstream model, use pass_through: true to automatically inherit its metadata.
  4. Choose materialization wisely: Use TABLE for models that are queried frequently or have expensive computations. Use VIEW for simple transformations or infrequently accessed models.