Course outline

dbt / Advanced: evidence, isolation and recoverable releases / Lesson 17

Orchestration, hooks and partial failures

Coordinate build outcomes and publication without assuming a project is one transaction or every retry is harmless.

About 4 min readContent reviewed
On this page

Lesson goals

  • Distinguish graph scheduling, test blocking and committed target state.
  • Review hooks and replay through explicit side-effect contracts.

A build follows dependencies but is not one global commit

dbt build can process selected supported models, tests, seeds, snapshots and other resources in DAG order. A failing error-severity test can block relevant downstream work under documented selection and dependency rules. That does not mean a previously built relation was rolled back, or every independent branch stopped before creating output. A library release needs a publication policy separate from individual node success. Decide whether consumers stay on a validated prior version until all required checks pass, and preserve which resources were built, failed or skipped during an interrupted invocation.

Retain a partial outcome rather than flattening it to failure

The local outcome model has a successful fact build, a failed key assertion and a skipped downstream report. It is not a native run_results schema, but it illustrates why “the command failed” is insufficient recovery evidence. The fact relation may now contain new data while the report still reflects an older publication. Identify the intended operation and target state before rerunning. A retry that rebuilds a deterministic table differs from one that repeats an additive hook or appends unkeyed rows. Keep the previous validated publication and source checkpoint visible in the recovery record.

json Illustrative technical example; logical results are reasoned, not engine-tested.
{"scope":"local partial-build model","outcomes":{"fct_loans":"built","loan_id_unique":"failed","daily_branch_activity":"skipped"},"publication":"retain previous validated report until reconciliation"}

A synthetic recovery model, not captured dbt output or proof that a real relation was committed.

Hooks add SQL and transaction assumptions outside the model query

A pre-hook or post-hook can execute SQL around a resource build. The illustrative audit insert is a real kind of side effect if run, so it is non-runnable and targets a fictional lab relation only. Repeated attempts could create duplicate audit rows unless an operation identity or supported idempotent protocol exists. Hook accumulation and ordering also matter across package, project and resource contexts. Transaction behavior depends on the adapter: helpers intended for transactional targets must not be assumed portable to databases where dbt uses different commit semantics. Review generated SQL and required permissions for every hook.

yaml Illustrative technical example; logical results are reasoned, not engine-tested.
models:
  - name: fct_loans
    config:
      post_hook:
        - "insert into lab_audit.model_runs(model_name) values ('fct_loans')"

Illustrative side-effect configuration only. No audit relation is created or written, and this unkeyed insert is not presented as replay-safe.

A lost acknowledgment creates uncertainty at the sink

A database can commit before a client loses its connection or receives a timeout. Do not infer rollback solely from that transport symptom. Reconcile known target identities and operation records through the approved recovery path before repeating an incremental update, seed load or external notification. External orchestration also needs retry budgets and ownership for overlapping scheduled runs. Two jobs writing the same target can conflict even when each DAG is internally correct. A scheduler’s success flag and a data product’s acceptance record are related but different evidence.

Recovery should be rehearsed with exact resource semantics

A separately authorized rehearsal should cover failure after a model build, before a required test, inside a hook and after a database commit acknowledgment is lost. Verify target state, source retention and the publication decision for each case. Snapshot history, incremental tables and ordinary full rebuilds have different replay rules. Do not use a blanket full refresh as the answer to every failure. This course launches no job, writes no audit row and invokes no retry. Local validation checks the outcome JSON and pure replay models only, with no transaction, orchestration or warehouse recovery test claimed.

Common errors and fixes

A failed build is assumed to undo every earlier model

Why it happens
DAG scheduling was confused with a project-wide transaction.
How to fix it
Inspect actual per-resource outcomes and target publication state.
Prevent it next time
Keep recovery and consumer-switch policy separate from command status.

A retry repeats an unkeyed audit insert

Why it happens
Hook side effects were not designed for repeated attempts.
How to fix it
Use a supported operation-key or idempotent audit protocol.
Prevent it next time
Review every hook with failure and retry scenarios.

A connection timeout is treated as proof of no write

Why it happens
Transport uncertainty was confused with a known database outcome.
How to fix it
Reconcile committed state before replaying effects.
Prevent it next time
Persist source and operation identity for recovery.

Check your understanding

1. What can coexist after the local failed-build model?

Show worked solution

The fact may be newly built, its required assertion failed and the report skipped or left at an older state. Determine the actual target and publication versions before retrying. The JSON illustrates possible partial state, not an atomic rollback guarantee.

2. Why is the shown audit hook not replay-safe by itself?

Show worked solution

It inserts a new row without an operation identity or deduplication rule. A repeated attempt can add another row even if the model data is unchanged. Design and verify the audit protocol under the actual adapter transaction behavior rather than assuming hook timing provides exactly-once effects.

Key takeaways

  • A graph build can leave meaningful partial data state.
  • Hooks and retries require explicit side-effect and recovery contracts.

Official references