All dbt Labs exams

Free dbt Analytics Engineering Certification Exam practice test: 30 questions with answers

30 original questions for dbt Analytics Engineering Certification Exam, drawn from every topic area. Answer each one to see whether you got it right and why. No sign-up.

Free questions
30
Full bank
112 questions
Real exam
65 questions, 120 min
Passing score
65%

dbt Analytics Engineering Certification Exam exam guide: topics, cost and format

All 30 dbt Analytics Engineering Certification Exam questions with answers

The same questions as the test above, grouped by exam topic. Open any question to see the answer and explanation.

Developing and optimizing dbt models (5 questions)

  1. Question 1

    A data team maintains an events model with roughly 500 million rows. Each run should add only the newest events, keep the existing history, and avoid rescanning the whole source table. Which materialization fits best?

    1. AAn incremental model whose is_incremental() filter selects only the newest rows on each run
    2. BAn ephemeral model, because dbt inlines it as a common table expression in each query that uses it
    3. CA table that is fully rebuilt on every run, so the output always mirrors the current source data
    4. DA view, because the warehouse recalculates the underlying query each time the model is read
    Show answer and explanation
    Correct answer: A

    An incremental model builds the full table once and, on later runs, its is_incremental() block limits the work to new rows, so history is kept without a full scan. A view stores no data, an ephemeral model is only inlined SQL that is never persisted, and a full-rebuild table reprocesses every row on every run.

  2. Question 2

    A team configures a model with the microbatch incremental strategy. Which description matches how this strategy works?

    1. AThe model lists unique_key columns, and each run merges the incoming rows into the existing table on those keys
    2. BThe model names an event_time column and a batch_size such as day, and dbt runs each period as its own batch
    3. CThe model writes to a staging table, and dbt renames that table into place after a full scan of the source
    4. DThe model has a Jinja loop that generates one INSERT statement for each distinct value of a partition column
    Show answer and explanation
    Correct answer: B

    Microbatch splits the input into time-based batches using the event_time column and batch_size, and each batch is processed as its own unit. A unique_key merge describes a different incremental approach, a staging-table rename is not how microbatch works, and a per-value Jinja loop is not part of the strategy.

  3. Question 3

    A team wants to apply a statistical function from a Python library to the output of an upstream dbt model. Which statement about Python models is accurate?

    1. Adbt compiles the Python file into SQL, so the library function runs inside the warehouse query engine
    2. BThe model function can return several dataframes, and dbt creates one table for each of them
    3. CThe script runs on the developer's laptop, and dbt uploads the result to the warehouse afterwards
    4. DThe model function receives a dbt object for ref and source calls and returns a single dataframe
    Show answer and explanation
    Correct answer: D

    A Python model defines a model(dbt, session) function, uses dbt.ref() and dbt.source() to read upstream relations, and returns one dataframe that dbt writes to the warehouse. It runs on the platform's Python runtime rather than being compiled to SQL, and it returns only one dataframe per model.

  4. Question 4

    A team needs to keep a history of every change to customer mailing addresses, with start and end dates for each version of a row. Which setup meets this need?

    1. AA snapshot defined in YAML with the timestamp strategy, a unique_key, and an updated_at column
    2. BA view over the source table, with grants set so analysts can query the past versions of each row
    3. CAn incremental model with a merge on customer_id that overwrites each changed address row in place
    4. DAn ephemeral model that copies each run's rows into the target schema with a timestamp suffix
    Show answer and explanation
    Correct answer: A

    A YAML snapshot with the timestamp strategy adds a new version of a row when updated_at changes and records dbt_valid_from and dbt_valid_to, which gives slowly changing history. A merge overwrites rows so history is lost, a view stores no history, and an ephemeral model is only a CTE that is never persisted.

  5. Question 5

    An incremental model stores exactly one row per order_id. The source sometimes re-sends an order with corrected amounts, and the target must keep only the latest values for each order. Which configuration handles this?

    1. AStrategy append with no unique_key, so each incoming row is added to the end of the existing table
    2. BAn ephemeral model, so the corrected amounts are inlined into each downstream query and never stored in the warehouse
    3. CA snapshot with the timestamp strategy, which stores each corrected amount as an additional dated version of the order row
    4. DStrategy merge with unique_key set to order_id, so a matching row is updated and a new key is inserted
    Show answer and explanation
    Correct answer: D

    A merge incremental strategy with unique_key uses the key to update an existing row or insert a new one, so each order_id stays unique. Append adds rows without checking keys, which creates duplicates, a snapshot keeps dated versions and so several rows per key, and an ephemeral model is never stored.

Managing dbt models governance (5 questions)

  1. Question 6

    A downstream team depends on the exact column names and data types of a customer mart. The team wants the build to fail if a column is renamed or its type changes. Which configuration does this?

    1. AA model contract with enforced set to true, and a declared data_type for each column in the YAML
    2. BA detailed description on each column, so that schema changes are visible in the generated documentation
    3. CA not_null generic test on every column, so any schema change is reported during dbt test
    4. DA table materialization, so that the warehouse keeps a copy of the previous schema for comparison
    Show answer and explanation
    Correct answer: A

    With an enforced model contract, dbt compares the model's columns and declared data types with the YAML during the build and fails when they do not match. Null tests check values rather than structure, descriptions only document the model, and a table materialization does not keep schema history.

  2. Question 7

    A team publishes version 2 of a shared orders model while some consumers still reference version 1. Which statement about model versions is accurate?

    1. AEach version must live in a separate dbt project, because two versions of one model cannot share a project
    2. BA ref with a v argument pins a consumer to one version, while an unversioned ref uses the latest version
    3. CThe warehouse drops older versions automatically once a newer version is built, forcing an immediate migration
    4. DUnversioned refs stop working when a new version appears, so every consumer must update its code together
    Show answer and explanation
    Correct answer: B

    Model versions let a consumer reference a specific version with ref('orders', v=1), while an unversioned ref resolves to the latest_version. A single project can hold several versions, and the warehouse does not delete an older version because a newer one exists.

  3. Question 8

    An analytics engineer wants to retire version 1 of a model in stages. Consumers still using it should be warned, giving them time to migrate. What should the engineer do?

    1. ADelete version 1 from the YAML at once, because dbt rewrites every existing ref to version 2 automatically
    2. BChange version 1 to ephemeral so it is hidden from consumers while the migration is in progress
    3. CSet a deprecation_date on version 1 in the YAML so dbt warns consumers that the version is being retired
    4. DRename version 1 with an old_ prefix so that existing refs keep resolving to the same table in the warehouse
    Show answer and explanation
    Correct answer: C

    A deprecation_date marks a version as being retired, and dbt issues warnings to consumers who still reference it, which gives them time to move to a newer version. Deleting the version does not rewrite refs, ephemeral materialization hides nothing from consumers, and renaming breaks existing references.

  4. Question 9

    Which two statements about constraints declared in model YAML are accurate? (Choose two.)

    1. AA check constraint declared in YAML runs as a singular test during dbt test and reports the rows that break it
    2. BConstraints are written to the database during the build only when the model's contract is enforced
    3. Cdbt checks constraint values when it parses the project, so invalid values fail before any SQL is executed
    4. DSome warehouses record certain constraints, such as primary keys, without enforcing them, so tests may still be needed
    5. EDeclaring a unique constraint makes a separate unique generic test unnecessary on every warehouse
    Show answer and explanation
    Correct answer: B, D

    Constraints in YAML become part of the model's DDL only when its contract is enforced, and some platforms accept constraints as metadata without enforcing them. Constraints are not run as tests, are not checked during parse, and cannot replace unique tests on every warehouse.

  5. Question 10

    A staging model has a model contract with enforced set to true. A developer adds a new column to the model's SQL but does not add it to the YAML. What happens on the next build?

    1. Adbt adds the new column to the YAML automatically, and the build continues with the contract updated to match
    2. BThe build fails, because the SQL returns a column that the enforced contract in the YAML does not declare
    3. CThe build succeeds, and dbt test reports a warning for the column until it is documented in the YAML
    4. DThe new column is dropped silently, since dbt only materializes the columns that are declared in the YAML
    Show answer and explanation
    Correct answer: B

    When a contract is enforced, dbt compares the SQL output with the declared columns and data types during the build and fails on any mismatch. dbt never edits YAML on its own, and an enforced contract neither drops columns silently nor lets the build pass with a warning.

Debugging data modeling errors (4 questions)

  1. Question 11

    A model fails with a Database Error about an invalid identifier in a SELECT that uses several ref() calls and macros. The engineer wants to see the SQL that dbt actually sent to the warehouse. Where should the engineer look?

    1. AThe seeds folder, where dbt saves a copy of each model's SQL so it can be reloaded after a failure
    2. BThe raw model file, because the warehouse executes the Jinja inside it exactly as it is written in the source
    3. CThe dbt_project.yml file, which keeps a copy of each model's SQL after the most recent successful run
    4. DThe compiled and executed SQL under the target directory, with Jinja already expanded into plain SQL
    Show answer and explanation
    Correct answer: D

    dbt writes the Jinja-expanded SQL to target/compiled and the statement it executes to target/run, which is what the warehouse actually received. The raw model file still contains Jinja the warehouse never sees, and dbt_project.yml and the seeds folder do not store model SQL.

  2. Question 12

    A run stops at the start with a Compilation Error saying a node was not found for a ref call, and no SQL reaches the warehouse. What is the most likely cause?

    1. AThe warehouse rejected the SQL syntax because a keyword in the select list was misspelled
    2. BThe warehouse connection timed out while the first model was materializing, so later models were skipped
    3. CThe incremental filter compared two columns with incompatible data types during the build step
    4. DThe ref call names a model that is not in the project or an installed package, often because of a typo
    Show answer and explanation
    Correct answer: D

    A missing node error is raised at compile time when a ref() name cannot be matched to any model or package node, usually because of a typo or a package that is not installed. The other options describe Database Errors or connection failures, which only occur once SQL reaches the warehouse.

  3. Question 13

    After an engineer edits a schema YAML file, dbt fails before any model runs and points to a line inside that YAML file. Which change most likely caused the failure?

    1. AA key was indented under the wrong parent, so dbt cannot parse the structure of the properties file
    2. BThe run used the --full-refresh flag, which forces every incremental model to rebuild its table
    3. CThe target password in profiles.yml was rotated, so the warehouse refused the login
    4. DA model's SQL called a macro that no installed package defines, so the compile step stopped
    Show answer and explanation
    Correct answer: A

    A YAML parse problem, such as a wrong indent or a key in the wrong place, is reported with the file and line before dbt runs any SQL. A rotated password fails when dbt connects, a missing macro is a SQL compile error inside a model file, and --full-refresh only changes how incremental models build.

  4. Question 14

    A developer wants a dbt build to stop scheduling new nodes as soon as any node fails. Which flag does this?

    1. A--fail-fast, which stops the run after the first failure instead of starting other independent nodes
    2. B--warn-error, which turns warnings into errors so that the run exits with a failure status
    3. C--no-partial-parse, which forces dbt to parse every project file again before the run starts
    4. D--debug, which prints detailed logs for each node while the run continues until every node finishes
    Show answer and explanation
    Correct answer: A

    The --fail-fast flag (also -x) makes dbt stop after the first failure rather than continuing with independent nodes. --warn-error only changes how warnings are treated, --no-partial-parse forces a full parse, and --debug only increases log detail.

Troubleshooting and optimizing dbt pipelines (4 questions)

  1. Question 15

    A nightly dbt build reports an error on a staging model. Several mart models that read from it show as skipped. Which nodes did dbt skip because of this failure?

    1. AThe upstream source tables feeding the failed staging model, since dbt re-checks their freshness
    2. BThe models and tests downstream of the failed staging model that depend on its output
    3. CEvery model in the same schema as the failed staging model, regardless of how they depend on it
    4. DOnly the generic tests attached to the failed staging model, while its child models still run
    Show answer and explanation
    Correct answer: B

    When a node fails in dbt build, dbt skips the descendants that depend on it, while parents that already completed are unaffected. Upstream sources are not skipped, schema membership does not decide skipping, and child models do not keep running when their parent fails.

  2. Question 16

    A developer wants to validate a change in a personal dev schema using data that matches production, without rebuilding every table. The team keeps the manifest from the last production deploy. Which command fits best?

    1. Adbt run with a full refresh of every model, so each table is rebuilt from the sources in the dev schema
    2. Bdbt clone with the production manifest as state, so the matching production relations are cloned
    3. Cdbt seed with the production manifest, so each seed file is reloaded from the production warehouse
    4. Ddbt snapshot with the production manifest, so every source table is recorded as a new historical version
    Show answer and explanation
    Correct answer: B

    dbt clone uses a state manifest to identify production relations and creates clones of them in the target schema, zero-copy where the platform supports it. A full refresh rebuilds tables from sources, seeds reload static CSV files, and snapshots record history instead of copying tables.

  3. Question 17

    A nightly job runs many independent staging models one after another, so the run takes too long. Which profile setting most directly lets more of these models build at the same time?

    1. AA higher threads value in the target profile, which sets how many nodes run concurrently
    2. BA --full-refresh flag on the command, which forces every model to recompute its full history
    3. CA larger batch_size on each model, which tells dbt to combine several staging models into one query
    4. DTurning off every test during the run, which removes the wait between each model and its tests
    Show answer and explanation
    Correct answer: A

    The threads setting in the target profile controls how many nodes dbt runs in parallel, as long as their upstream dependencies are complete. batch_size applies to microbatch models, full refresh changes what incremental models rebuild, and skipping tests does not add concurrency.

  4. Question 18

    Which two actions help you find where a failing pipeline began? (Choose two.)

    1. ARead run_results.json in the target directory to see the status each node reported in the last invocation
    2. BDelete the target directory so that dbt rebuilds the DAG from the warehouse catalog on the next run
    3. CSet threads to 1 so that the failing model reproduces faster against the warehouse
    4. DRun dbt ls with a graph selector such as +failing_model to list that model and its upstream nodes
    5. ERun dbt deps to rebuild every table in the failing lineage from the installed package definitions
    Show answer and explanation
    Correct answer: A, D

    run_results.json records each node's status from the last invocation, and dbt ls with a graph operator lists a suspect model together with its upstream nodes. Deleting target does not rebuild the DAG from the catalog, lowering threads does not speed up reproduction, and dbt deps only installs packages.

Implementing dbt tests (4 questions)

  1. Question 19

    A model's order_id column must hold a distinct value on every row, and it must never be null. Which approach is the standard way to check both rules?

    1. AA snapshot on the model, because snapshots reject duplicate and null keys before they reach the target table
    2. BThe unique and not_null generic tests declared under the order_id column in the model's properties YAML
    3. CAn accepted_values test that lists every valid order_id, so that nulls and duplicates show up as unknown values
    4. DA severity of warn in the model config, so that duplicate or null rows are logged without failing the build
    Show answer and explanation
    Correct answer: B

    The unique and not_null generic tests are built-in checks declared on a column in YAML, and they fail when duplicate or null values exist. Snapshots record history rather than validate keys, accepted_values cannot practically list every valid ID, and severity only changes how a failure is reported.

  2. Question 20

    Which two statements about singular tests are accurate? (Choose two.)

    1. AA singular test is a SQL file in the tests directory that selects the rows breaking a rule, and it passes when no rows return
    2. BA singular test is declared as a block under a column in a properties YAML file, next to its accepted values
    3. CA singular test must be written as a macro with a test block, so it cannot contain a plain SELECT statement
    4. DA singular test can express a rule that spans several columns or joins, which one generic test may not express easily
    5. EA singular test runs during dbt parse, so a failing rule stops the project before any SQL is executed
    Show answer and explanation
    Correct answer: A, D

    Singular tests are standalone SQL files whose returned rows count as failures, which suits rules spanning several columns or tables. A column-level YAML block describes a generic test, custom generic tests are macros, and tests run during dbt test or dbt build rather than during parse.

  3. Question 21

    A team wants one reusable check that confirms a numeric column in many models stays above a minimum value, with each model supplying its own minimum. Which approach matches this need?

    1. AAn exposure for each model that records the minimum value in its description field so reviewers can see it
    2. BThe same singular test SQL copied into each model's folder, with the minimum edited by hand in every copy
    3. CA severity of warn added to each model, so that the threshold check runs with lower priority than the others
    4. DA custom generic test macro with a test block, applied from YAML with the column and minimum passed in
    Show answer and explanation
    Correct answer: D

    A custom generic test is a macro with a test block that accepts model and column arguments, so YAML can apply it to any column with a different threshold. Copied singular tests duplicate the logic, severity does not create a check, and exposures describe downstream uses rather than data rules.

  4. Question 22

    A model contains conditional logic and several joins. The team wants to confirm the SQL returns an exact expected output for fixed input rows, without reading production data. Which dbt feature fits?

    1. ASource freshness checks with warn_after and error_after thresholds on each input table
    2. BA snapshot of the output table, which records the rows from each run and compares them to the prior run
    3. CUnit tests declared in YAML with given input rows and an expected output for the model under test
    4. DA singular test that runs a SELECT against production tables and reports rows that differ from a stored file
    Show answer and explanation
    Correct answer: C

    Unit tests give a model fixed mock inputs and compare its result to an expected output, so the logic is checked without relying on warehouse data. Freshness checks measure load age, snapshots store history, and the singular test reads production tables, which the team wants to avoid.

Implementing and maintaining external dependencies (4 questions)

  1. Question 23

    A BI dashboard reads from fct_orders and dim_customers. The team wants the dbt docs lineage graph to show the dashboard as a downstream consumer of those two models. Which change does this?

    1. AAdd the dashboard's table name to the sources YAML so that it appears upstream of both models in the graph
    2. BAdd a seed file listing the dashboard's filters, so that the lineage graph links those filters to both models
    3. CCreate a materialized view named after the dashboard, so that dbt docs draws it as a downstream model node
    4. DDeclare an exposure in YAML with a type such as dashboard, an owner, and depends_on refs to both models
    Show answer and explanation
    Correct answer: D

    An exposure is a YAML definition of a downstream use such as a dashboard, and its depends_on references place it in the lineage graph. Listing the dashboard as a source puts it upstream, a materialized view is a model rather than an exposure, and seeds hold static data rather than describe consumers.

  2. Question 24

    Which statement about exposures in dbt is accurate?

    1. AAn exposure replaces the sources YAML, because it declares the raw tables that each model reads from
    2. BAn exposure is a lineage node that describes a downstream use of data and has no table of its own
    3. CAn exposure is a freshness check that compares the newest row in a dashboard table with the current time
    4. DAn exposure is executed by dbt run, which refreshes the dashboard after each model in the DAG has finished
    Show answer and explanation
    Correct answer: B

    Exposures document consumers such as dashboards, notebooks, and applications, and they appear in the DAG and docs without dbt building anything for them. They do not declare sources, dbt run does not execute them, and they are not freshness checks.

  3. Question 25

    An ingestion job should load new rows into a raw orders table at least every 12 hours. The team wants dbt to warn after 12 hours without new data and to fail after 24 hours. How should the source be set up?

    1. ASet materialized to incremental on the source table, so dbt reloads it and records the time of each arrival
    2. BAdd a not_null test on the updated_at column, so dbt build fails whenever the timestamp column is empty
    3. CSet a loaded_at_field on the table, add warn_after of 12 hours and error_after of 24 hours, then run dbt source freshness
    4. DAdd a snapshot on the raw orders table, so every run compares the newest row with the previous timestamp
    Show answer and explanation
    Correct answer: C

    Source freshness uses loaded_at_field to measure the age of the latest load and applies the warn_after and error_after thresholds when dbt source freshness runs. A not_null test checks for empty values, materialization applies to models rather than sources, and a snapshot records history instead of measuring age.

  4. Question 26

    Which two statements about source freshness are accurate? (Choose two.)

    1. AFreshness compares the most recent value of the loaded_at_field with the current time to decide whether to warn or error
    2. BFreshness checks can run on a source without a loaded_at_field by counting the rows in the table
    3. Cdbt build does not run freshness checks by default, so dbt source freshness must be run as a separate command
    4. DFreshness failures are reported as test failures, so they appear in dbt test output and block dbt build
    5. EA freshness check needs a snapshot of the source table before the first threshold can be evaluated
    Show answer and explanation
    Correct answer: A, C

    Freshness compares the newest loaded_at_field value with the current time against the warn_after and error_after thresholds, and it runs through dbt source freshness rather than as part of dbt build. Row counting is not a freshness method, freshness results are reported by the source freshness command rather than as test failures, and no snapshot is required.

Leveraging the dbt state (4 questions)

  1. Question 27

    A CI job should build only the models changed in a pull request, plus every model that depends on them, and compare against the production manifest. Which command fits?

    1. Adbt build --select state:modified with --state pointing at the production manifest
    2. Bdbt run --full-refresh so that every model is rebuilt from the source tables
    3. Cdbt build --select state:modified+ with --state pointing at the production manifest
    4. Ddbt build --select result:error so that only models that failed in the last run execute
    Show answer and explanation
    Correct answer: C

    The state:modified+ selector picks the changed nodes and their downstream children, and --state gives dbt the earlier manifest to compare against. state:modified alone omits the children, a full refresh rebuilds everything, and result:error selects nodes that failed in the previous run.

  2. Question 28

    What does a state selector such as state:modified compare?

    1. AThe row counts in the development schema against the row counts in the production schema for each table
    2. BThe run_results.json from the current invocation against the results from the invocation before it
    3. CThe node definitions in the current project against the manifest.json saved from an earlier run
    4. DThe git commit history of each model file against the change log stored in the warehouse metadata
    Show answer and explanation
    Correct answer: C

    State selectors compare the project being run with a previously saved manifest.json, supplied through --state, to find new, modified or unchanged nodes. Row counts, run results and git history are not what state:modified compares.

  3. Question 29

    A developer changes one mart in a personal dev schema. The upstream staging models were not changed and exist only in production. The developer wants to avoid building them. Which option fits best?

    1. ACopy the production staging tables into the dev schema with a manual SQL script before each run
    2. BAdd every upstream staging model to --select so the dev schema holds its own copy before the mart runs
    3. CRun dbt compile on the staging models, which saves their results to the dev schema for later reuse
    4. DRun with --defer and --state so references to unchanged upstream models point at production relations
    Show answer and explanation
    Correct answer: D

    With --defer and a state manifest, dbt resolves references to nodes that were not built in the current run to their production relations, so only the changed mart is built in dev. Building every upstream model defeats the goal, hand-copied tables are error-prone, and dbt compile does not store results in the warehouse.

  4. Question 30

    A dbt build stopped with an error on one model because of a short warehouse outage. Other nodes finished or were skipped. After the outage, the engineer wants to rerun only the nodes that failed or were skipped. Which command does this?

    1. Adbt deps followed by dbt run, which refreshes the packages and then rebuilds all models in order
    2. Bdbt build --full-refresh, which rebuilds every model so the earlier partial run is replaced
    3. Cdbt retry, which reruns the nodes that failed or were skipped in the previous invocation
    4. Ddbt compile, which checks the SQL of every model before any node is run again
    Show answer and explanation
    Correct answer: C

    dbt retry uses the last invocation's results to rerun only the nodes that errored or were skipped. A full refresh rebuilds nodes that already succeeded, dbt deps only installs packages, and dbt compile does not execute models.