How audits work
Violation audits pass when their query returns zero rows. Measurement audits produce one value and optionally a sample count; their outcome ispass, warn, fail, or insufficient.
For error severity audits:
- Full table builds: SQLBuild materializes into a staging table, runs audits against it, and only promotes to the target if all audits pass. If any fail, the staging table is kept for inspection and the production table is untouched.
- Incremental models: Delta-phase audits validate each batch before DML is applied. If an audit fails, the batch is not applied.
warn severity audits, the build continues and the failure is reported in the output.
Measurement audits
A reusable measurement audit separates the aggregate query from optional bounded evidence:minimum_samples keeps low-volume measurements distinct as insufficient rather than inventing a
pass or failure. Evidence is diagnostic and bounded by evidence_limit; the measurement and
threshold determine the outcome.
Audit factories
Use a Python audit factory when many related audit instances should be generated from one reviewed declaration:MODEL (audit_factories [order_quality]). Generated cases compile to the same audit
contract as directly authored instances.
Result history
Native warehouse adapters best-effort append confirmed audit outcomes to_sqlbuild_audit_results. Rows are immutable and use deterministic IDs, so retrying the same result
is idempotent. Projection failure is reported separately and does not change the audit outcome or
command exit code. Lifecycle sinks can also consume the corresponding audit_completed fact.
Built-in audits
SQLBuild includes four generic audits out of the box. You do not need to define these inaudits/generic/ - they are available automatically:
Using built-in audits
Attach them in theMODEL() header like any generic audit:
Overriding built-in audits
If you define a generic audit with the same name as a built-in (e.g.audits/generic/not_null.sql), your definition takes precedence. SQLBuild emits a warning so you’re aware of the override:
Custom generic audits
Beyond the built-ins, you can define reusable SQL templates underaudits/generic/. They use @parameter placeholders that are resolved by the audit engine at compile time.
Audit parameters
Generic audit SQL uses@name for parameter placeholders. These are resolved by the audit engine, not the general SQL interpolation system:
Generic and singular audit SQL uses macros, constants, and enums available from the audit file under
audits/, not from a model or source that uses the audit. See
How Visibility Works.
Attaching custom generic audits
Singular audits
Singular audits are standalone SQL files. Their canonical home isaudits/singular/, and they
reference models directly. They’re useful for one-off checks that don’t fit a reusable template.
For backward compatibility, singular audits directly under audits/ or another non-generic
child directory continue to compile.
__ref() calls in the query. If the audit references a single model, it attaches to that model. If it references multiple models, SQLBuild attaches it to the latest (most downstream) model in the DAG. If attachment can’t be inferred, the audit runs at the end of the build.
Source audits
Sources support the same audit system as models. Audits attached to sources run before any dependent model is built:error severity fails, all downstream models that depend on that source are blocked. This lets you catch data quality issues at the source before any transformations run.
Severity
Set the default severity in
sqlbuild_project.toml:
MODEL() header:
Run scope
Audits on incremental models can run at different lifecycle phases:error severity block DML before the target is updated. This is visible in the build output as audit (d) for delta-phase and audit (f) for final-phase:
4/4 indicates the audit passed for all 4 microbatch batches.
If a model is not incremental, delta_and_final degrades to final automatically.
Running audits standalone
SQLBUILD_CONCURRENCY, or in project settings. For example, sqb audit --concurrency 8 runs up
to eight selected audits at once, using one warehouse connection per active worker. Increase this
limit deliberately because parallel queries can increase warehouse load and cost. See
sqb audit for precedence, ordering, and cancellation details.
