pre-hooks and post-hooks let you inject SQL or macros immediately before or after each node (model, snapshot, seed, etc.) runs. They are useful for automating grants, audit logging, statistics refreshes, and similar tasks.
This article assumes the stable behavior described in the official docs and lays out the precautions you need to use hooks safely in production, plus the comparison points that come up on the Analytics Engineer exam.
A pre-hook is evaluated and executed immediately before its node runs; a post-hook runs immediately after. Hook bodies can be templated with Jinja and have access to context such as this, target, var, and env_var.
These are node-level hooks, distinct from on-run-start / on-run-end, which fire only once at the start or end of the entire project run.
Across a full dbt run, on-run-start fires once at the very beginning. Then, for each node, dbt runs pre-hook → main SQL → post-hook in order, and finally on-run-end fires once at the end.
On most adapters, the main SQL and the pre/post hooks share a single transaction. Setting transaction: false (on adapters that support it) runs the hook in its own transaction. Auto-commit behavior for DML/DDL is warehouse-specific, so it is safer to isolate things like grants and session settings when appropriate.
Where hooks fit in the dbt run lifecycle
Post-hooks are well suited for grants and statistics refreshes against a relation that was just created or replaced. Pre-hooks fit prep work such as cleaning staging areas or temporary tables before the main SQL runs.
For session- or query-level settings, combine hooks with sql_header and adapter-specific config (such as Snowflake's query_tag) for a more robust result.
You can apply hooks broadly through dbt_project.yml model hierarchies or individually via a model's config() block. Multiple entries can be declared as a list and run top-to-bottom, and macro calls are allowed.
Where the adapter supports it, transaction: false isolates the hook in its own transaction. This is helpful for grants, logging, and other operations you do not want rolled back together with the main SQL on failure.
Examples (dbt_project.yml, in-model config, and a macro)
# dbt_project.yml (excerpt)
models:
my_project:
+post-hook:
- sql: grant select on {{ this }} to role ANALYST
transaction: false
- "{{ log('built ' ~ this, info=True) }}"
# models/fct_orders.sql (per-model hooks)
{{ config(
materialized='table',
pre_hook=[
"delete from {{ ref('load_control') }} where model='{{ this.identifier }}'"
],
post_hook=[
"{{ insert_audit_record(this, 'fct_orders') }}"
]
) }}
select *
from {{ ref('stg_orders') }}
# macros/insert_audit_record.sql (audit-log macro)
{% macro insert_audit_record(relation, model_name) %}
{% if execute %}
insert into {{ ref('audit_log') }}(model, relation, executed_at, environment)
values ('{{ model_name }}', '{{ relation }}', current_timestamp, '{{ target.name }}');
{% endif %}
{% endmacro %}On the Analytics Engineer exam, the typical talking points are hook granularity, execution timing, and transaction boundaries. Be ready to instantly pick the right hook for a given scenario.
In particular, memorize this split: on-run-start/end for once-per-run audit records, post-hook for grants applied to each model, and pre-hook for prep-time cleanup.
| Hook type | Timing / granularity | Transaction | Primary use |
|---|---|---|---|
| pre-hook | Immediately before each node runs | Usually shares the main SQL's transaction; can be isolated where the adapter supports it | Preparing temp tables, cleanup, setting session prerequisites |
| post-hook | Immediately after each node runs | Usually shares the main SQL's transaction; isolate to make grants and similar work safer | GRANT, audit logs, statistics refreshes |
| on-run-start / end | Once at the start and end of the run | Runs on its own, independent of any node | Run-wide audit logging, environment setup and teardown |
Hooks are powerful, but mishandling transaction boundaries or ordering can lead to unintended side effects. The following guidelines keep things stable.
Analytics Engineer
問題 1
A team wants to insert a single audit-log row at the start of every dbt run, and grant privileges immediately after each model is created or updated. Which configuration fits best?
正解: A
Inserting a single audit row per run fits on-run-start. Granting privileges right after a model is created fits a per-node post-hook. A pre-hook runs before the main SQL, and GRANT statements belong on a relation that already exists.
Do pre/post hooks work on ephemeral models?
No. Ephemeral models do not produce a physical relation, so pre/post hooks do not apply to them. Apply grants and other side effects on the downstream physical relations instead.
How do transactions behave, and what happens when a hook fails?
On most adapters, pre/post hooks run inside the same transaction as the main SQL. If a pre-hook fails, the main SQL never runs. A post-hook failure marks the node as failed, but the relation may already have been created or updated. Auto-committed DDL and other adapter-specific quirks exist, so separate hooks with transaction: false where needed and keep the SQL idempotent.
How should you debug and verify hooks?
Start with dbt compile to inspect the generated SQL, and use --debug for detailed logs. Macro-driven hooks can be tested in isolation via dbt run-operation. Emitting runtime info with the log() macro is also an effective verification technique.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
dbt Models: SQL-Defined Transformation Units (2026)
Model fundamentals — SELECT-based definitions, naming, refs,...
dbt Analytics Engineering Exam: Complete Guide (2026)
Pass the AE Certification — scope, weighting, sample questio...
dbt Cloud vs dbt Core: Feature & Cost Comparison (2026)
Honest comparison of dbt Cloud vs. dbt Core — IDE, scheduler...
dbt Project Structure: models/seeds/macros Layout (2026)
Recommended dbt project layout — models, seeds, macros, snap...
dbt_project.yml Explained: Every Config (2026)
Every dbt_project.yml setting that matters — paths, vars, ma...