This folder is a minimal dbt Core project that works with Orchestra’s state orchestration for dbt Core: freshness, build_after, and skipping or reusing work based on upstream change signals.
- Seeds (
dbt/seeds) load CSV data into a raw schema.stg_eventsusesref('raw_events')so dbt runs the seed before staging (asource()-only reference can run in parallel with the seed and fail). Sources indbt/models/schema.ymlstill document the logical raw layer and source freshness (warn_after,loaded_at_field) for Orchestra and the manifest. - Staging → intermediate → marts show a small DAG; the mart
mart_daily_totalssetsfreshness.build_afterso Orchestra can reason about when downstream models should run relative to upstream updates (see dbt Core state management). - Macros (
dbt/macros/audit_run_id.sql) and snapshots (dbt/snapshots/snap_mart_daily_totals.sql) mirror common real projects without extra packages.
Use this tutorial project to exercise all supported stateful permutations:
| Scenario | Config / command | Behavior |
|---|---|---|
| Stateful disabled pass-through | ORCHESTRA_USE_STATEFUL=false then orc dbt build |
Wrapper delegates directly to dbt; no state orchestration. |
| Stateful with local file backend | ORCHESTRA_USE_STATEFUL=true, ORCHESTRA_STATE_FILE=.orchestra/dbt_state.json, no ORCHESTRA_API_KEY |
State is loaded/saved from local JSON and clean nodes can be reused. |
| Stateful with HTTP backend | ORCHESTRA_USE_STATEFUL=true, ORCHESTRA_API_KEY=... |
State is loaded/saved through Orchestra API. |
| Stateful with S3 backend | ORCHESTRA_USE_STATEFUL=true, ORCHESTRA_STATE_FILE=s3://bucket/key, no API key |
State is loaded/saved in S3 (requires dbt-orchestra[s3]). |
| Full refresh override | any stateful backend + orc dbt build --full-refresh |
Reuse logic is bypassed for that run; state is still updated after execution. |
| Supported stateful commands | orc dbt run, orc dbt test |
Same orchestration flow as build: compute freshness, patch reusable nodes, update state. |
| Unsupported stateful command | orc dbt seed |
Pass-through to dbt even when use_stateful=true. |
To test functions in Postgres:
- Create a
functionsfolder - Create a
schema.ymlfile (content below) - Create a
{{function_name}}.sqlfile (content below) - Reference the function in a model
Schema.yml:
functions:
- name: is_positive_int # required
description: My UDF that returns 1 if a string represents a naked positive integer (like "10", "+8" is not allowed). # optional
config:
schema: raw
database: "{{ target.database }}"
volatility: deterministic
arguments: # optional
- name: a_string # required if arguments is specified
data_type: text # required if arguments is specified
description: The string that I want to check if it's representing a positive integer (like "10")
default_value: "'1'" # optional, available in Snowflake and Postgres
returns: # required
data_type: integer # required
Function.sql:
SELECT CASE WHEN a_string ~ '^[0-9]+$' THEN 1 ELSE 0 END
Reference the function in a model:
select
id,
amount,
{{ function('is_positive_int') }}(amount::text) as is_positive_amount,
event_at,
customer_id
from {{ ref('raw_events') }}
Ensure uv sync --extra dev --extra adapters has been run.
-
Start Postgres:
docker run -d --rm -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=tutorial -p 5432:5432 --name tutorial-postgres postgres:18
-
Change to the tutorial/dbt directory:
cd tutorial/dbt -
If using local state file, create the file:
mkdir -p .orchestra echo '{"state":{}}' > .orchestra/dbt_state.json
-
Export connection settings and schema (names can be adjusted):
export PGHOST=127.0.0.1 PGPORT=5432 PGUSER=postgres PGPASSWORD=postgres PGDATABASE=tutorial DBT_SCHEMA=sao_tutorial DBT_PROFILES_DIR="$(pwd)"
-
Seed the database:
orc dbt seed
orc dbtcommands other thanbuild,runandtestare passed through todbt. -
Run a dbt build for the first time:
orc dbt build
Logs will show that stateful orchestration is enabled, and that because the state file has no state in it, no nodes are re-used. The
.orchestra/dbt_state.jsonfile will have been populated for each node. -
Run a dbt build again, now that we've hydrated the state file:
orc dbt build
This time, logs show that state was collected, and if the re-run happened within 5 minutes of the previous run, 3 nodes were re-used, avoiding unnecessary computation.
-
Amend the
models/schema.yamlfile'sconfig.freshnessblocks betweenorc dbt buildruns, to see how this affects how models are re-used. -
(Optional) To remove the Postgres container after testing, run:
docker rm -f tutorial-postgres
profiles.yml uses only environment variables. Do not commit warehouse passwords.
To integrate this functionality into your dbt Core project, see the repo-level README.md.