Skip to main content
Federate models are data transformations that run at query time on the embedded DuckDB engine. They can reference sources, seeds, build models, dbview results, and other federate models, making them ideal for creating the final dataset layer that responds to user parameter selections. Federate models are stored in the models/federates/ directory and can be written in SQL (DuckDB dialect) or Python.

File structure

SQL federate models

SQL federate models use the DuckDB dialect and support full Jinja templating with access to parameters, context variables, and user information.

Example SQL model

models/federates/fed_transactions_summary.sql

Available Jinja variables

The following variables are commonly used in federate models: The following variables are also available in federate models, but are less commonly used given the availability of ctx:

The ref() macro

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

Python federate models

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

Example Python model

models/federates/fed_transactions_summary.py

YAML configuration

The YAML configuration file specifies dependencies and other options:
models/federates/fed_transactions_summary.yml

Configuration fields

string
default:""
A description of the model for documentation purposes or for use by data consumers (such as AI agents).
list[string]
default:"[]"
List of model names this federate depends on. Optional for SQL models (derived from ref() calls), but required for Python models.
boolean
default:"false"
If true, the SQL model result is materialized as a TABLE in memory. If false, it’s created as a VIEW. This only applies to SQL models. See Eager vs lazy evaluation for details.
list[object]
default:"[]"
Column metadata definitions as a list.

Eager vs lazy evaluation

The eager setting controls how SQL federate models are created in DuckDB: When enabled:
  1. The federate model result is materialized as a TABLE in the temporary in-memory DuckDB database per request
  2. Subsequent references to this model read from the materialized table
  3. This prevents redundant computation when the same result is used multiple times
The eager setting only applies to SQL federate models. Python federate models use polars LazyFrames or DataFrames (depending on what is returned by the model). However, they are registered with DuckDB when referenced by downstream SQL models, or collected as a DataFrame if used as the dataset response.

Using placeholders for SQL injection prevention

For user-provided values, use placeholders to prevent SQL injection:
models/federates/fed_transactions.sql
The $placeholder_name syntax (for DuckDB) is used in the query for parameterized execution. The placeholder can be set using context variables in pyconfigs/context.py. For instance:
pyconfigs/context.py

Connecting to datasets

In squirrels.yml, you reference a data model as the model for a dataset. The target model can be any type of data model (source, seed, build, dbview, or federate):
squirrels.yml

Best practices

  1. Use descriptive names: Prefix federate names with fed_ to distinguish them from other model types.
  2. Use context variables: Define complex logic in context.py and use simple context variable references in your SQL/Python models.
  3. Declare dependencies in YAML: Unlike SQL models which auto-detect dependencies via ref(), Python models require explicit depends_on in the YAML configuration. It is also recommended to declare dependencies in YAML for SQL models.
  4. Document conditional columns: If a specific column only exists based on parameter selections, use the condition field to document it. For example, if a column only exists when the group_by parameter is set to "Transaction", then the condition field should be set to ["group_by == 'Transaction'"].
  5. Use placeholders for user input: Always use set_placeholder() for values that come from user text input to prevent SQL injection.
  6. Mask sensitive data: Use conditional logic based on user fields to mask sensitive columns.
  • Sources - Configure source tables from external databases if loading to the VDL
  • Seeds - Static CSV data files
  • Build models - Materialized models in the VDL
  • Dbview models - Dynamic models that run on external databases
  • Context variables - Set context variables that transform parameter selections into meaningful values at runtime
  • ModelArgs - API reference for Python federate model arguments