Skip to main content
When you run 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 via ctx.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:
To make it the default for a project or target, set it in config instead of passing the flag every run:
The CLI flag takes precedence, followed by the selected target, explicit local settings, then project settings. When any source enables it, the planner removes models and functions from the selected scope if they have no pending work; models with any change reason, a pending backfill, or a changed upstream source are kept. Sources, seeds, and other non-model resources are always kept.

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 --select interacts 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.
Only table materializations support 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.
There is no external state database, no manifest files, and no state machine with transitions that can corrupt. The planner reads the latest row per identity, compares it against the compiled project, and writes new rows after successful builds. Old rows are retained as immutable history. State tables are read across all target schemas in the project, so fingerprints and freshness observations resolve consistently regardless of which schema a model targets. Use sqb janitor to prune old state history rows while retaining the latest per identity.

Virtual environments

Virtual environments store identities and change-tracking state in the VDE state backend (PostgreSQL or DuckDB) rather than in warehouse fingerprint tables, scoped per environment. See Virtual Environments: Building.