sqb plan or sqb build, SQLBuild compiles your project, compares it against the current warehouse state, and produces a plan. By default, SQLBuild runs your full selection - the same predictable behavior as a plain build, with nothing to configure.
Change-aware pruning is opt-in. Pass --changes-only (or set changes_only = true in config) to narrow the run to only stale work - unchanged models, seeds, audits, and Python nodes are then skipped automatically. The fingerprints and change reasons below are recorded on every successful build regardless, so change detection is ready the moment you enable pruning.
What is tracked
Every node in the graph has a versioned identity stored in_sqlbuild_fingerprints in the target schema. The planner reads these on every run and compares them against the compiled project.
Models and functions
Each model and function has a fingerprint derived from:- Query hash - the normalized SQL after macro expansion and reference resolution.
- Config hash - version-identity config values (materialization settings, contracts, hooks, custom config/placeholders).
- Function hashes - for models that depend on user-defined functions, the function’s own fingerprint is included. A function change cascades to all dependent models.
Seeds
Seeds are fingerprinted by content hash and load-affecting config. Unchanged seeds are not reloaded.Python nodes
Loaders, tasks, assets, checks, and hooks are fingerprinted by source-code hash, transitive project-dependency hashes (scoped to the git root, so third-party package changes don’t count), and decorator config. Python identity tracking is primarily a visual indicator in the plan: when a node’s identity changes, the plan shows source and dependency diffs. Unlike SQL models, the framework can’t observe a Python node’s external inputs (an API, a file, a service), so skip/run decisions are user-controlled viactx.skip() - the node’s own logic decides whether it needs to run. See Python node pruning.
Audits
Audits that already passed for the same model version identity are not re-run. When a model’s version changes, its audits are re-validated.Change reasons
The plan assigns a reason to each node that needs work:
By default, every selected node runs regardless of its reason. Under
--changes-only, nodes with no pending work are pruned and show as current in the plan output.
Changes-only mode
By default, SQLBuild executes all selected models regardless of whether they have changed.--changes-only narrows the scope to only models that are actually stale:
On this topic
- Cascade propagation - how a change signal propagates downstream, and how each materialization type responds.
- Source freshness - observing whether external source data has actually changed between runs.
- Selection and staleness - how
--selectinteracts with change detection, and the stale warnings that prevent silent partial rebuilds.
Reuse from production
When a model’s version identity matches a relation already built in another target, the planner can reuse that relation instead of rebuilding it, and can clone the upstream inputs a partial build needs from production. This uses the same fingerprints described above. See Reuse from production.Run despite unchanged
Some models depend on external data that isn’t tracked by source freshness, for example a table model that reads from an API-populated staging area.run_despite_unchanged forces a model to run periodically even when its version identity hasn’t changed.
always- run on every build regardless of state.- Duration (e.g.
24h,30d,90m) - run if at least the specified time has passed since the model’s upstream source freshness was last observed. Requires at least one upstream source with timestamp freshness tracking.
run_despite_unchanged. When triggered, downstream models are also marked as stale.
Python node pruning
When unchanged SQL models are skipped, read-side Python nodes (tasks, assets, checks) that depend on those models are also skipped. Loaders always run regardless of pruning, since they populate sources that the SQL graph depends on. Python nodes also have their own identity fingerprints: if a node’s source code or dependencies change, it runs even if its SQL dependencies haven’t.Warehouse-native state (standard mode)
In standard mode, all change-tracking state lives in the warehouse as append-only tables in the same schemas as your data:_sqlbuild_fingerprints- version identities for models, functions, seeds, and Python nodes. One row per successful build per identity._sqlbuild_source_freshness- source freshness observations. One row per successful build per source identity._sqlbuild_node_results- Python node runtime results (payload, metadata, status, errors). One row per execution per node.
sqb janitor to prune old state history rows while retaining the latest per identity.

