CertSafari

    Free DBT Analytics Engineering Sample Questions

    35 free sample questions from our bank of 438+, covering every exam domain, with answers and detailed explanations. Updated August 2026.

    Domain 1: Developing and optimizing dbt models

    Subdomain 1.14: Understanding advanced dbt materializations such as microbatch

    1.The microbatch materialization in dbt processes data in small, incremental batches to handle large volumes efficiently.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: ATrue

    • A. The statement is true because the microbatch materialization in dbt is designed to process data in small, incremental batches, which enables efficient handling of large volumes while avoiding full refreshes and reducing resource consumption.
    • B. The statement is false because the microbatch materialization does indeed operate by processing data in small batches, making the described behavior accurate; therefore, the correct answer is true, not false.

    Subdomain 1.10: Creating snapshots in YAML

    2.If you add a new column to the `check_cols` list of an existing snapshot, running `dbt snapshot` will retroactively invalidate all previous records by setting their `dbt_valid_to` because the newly included column's historical values may differ from the source.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: BFalse

    • A. The statement is false because adding a column to `check_cols` does not retroactively invalidate all previous records; dbt only compares current source rows with the latest snapshot record using the updated columns, and historical rows are not retroactively recomputed.
    • B. The statement is false because adding a column to `check_cols` does not automatically rewrite historical snapshot rows; dbt only updates records when the snapshot run detects a change in the checked fields between the current source row and the latest snapshot record, and historical rows are not retroactively recomputed from source history.

    Subdomain 1.10: Creating snapshots in YAML

    3.In dbt YAML snapshots, to define a composite `unique_key` consisting of multiple columns, you must provide the key as a ______.

    1. A.a single string with commas
    2. B.a list of column names
    3. C.a dictionary of column names
    Show answer & explanation

    Correct answer: Ba list of column names

    • A. Incorrect. A comma-separated string is not the correct format for a composite `unique_key` in dbt YAML snapshots. dbt expects a structured collection of column names, not a single string with commas.
    • B. Correct. In dbt YAML snapshots, a composite `unique_key` must be provided as a list of column names. This allows dbt to clearly identify the combination of columns that together uniquely identify each record.
    • C. Incorrect. A dictionary with column names as keys is not the required format for `unique_key` in dbt snapshots. The `unique_key` must be a list, not a dictionary, even though dictionaries are used in other YAML contexts.

    Subdomain 1.11: Selecting the optimal incremental strategy based on a dataset's characteristics

    4.The optimal incremental strategy for a dbt model should be selected based on the characteristics of the underlying dataset.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: ATrue

    • A. The statement is true because dbt offers incremental strategies like merge, insert_overwrite, and append, and the best choice depends on factors such as dataset size, volatility, and idempotency requirements.
    • B. The statement is false because selecting the optimal incremental strategy does depend on dataset characteristics; ignoring these can lead to inefficiencies or incorrect results.

    Subdomain 1.12: Validating model logic and schema definitions in dry-runs using the --empty flag

    5.You are working on a large incremental model that uses a `merge` strategy. You have added a new column and want to verify the DDL change without executing the full merge operation on millions of rows. Your development environment uses a separate schema. What is the most dbt-idiomatic approach?

    1. A.Run `dbt run --empty --select my_model` in your dev schema; this creates the table from scratch with the new schema and no rows.
    2. B.Run `dbt run --select my_model` in your dev schema; it will incrementally load data and include the new column.
    3. C.Use `dbt compile` to validate the SQL, then manually add the column to the production table.
    4. D.Run `dbt run --full-refresh --select my_model` in your dev schema to rebuild the table with the new column and all data.
    Show answer & explanation

    Correct answer: ARun `dbt run --empty --select my_model` in your dev schema; this creates the table from scratch with the new schema and no rows.

    • A. Correct. The `--empty` flag creates the table with the new schema (including the new column) but without any data, which is ideal for validating DDL changes without processing rows. This is the most efficient and idiomatic way to test schema changes in a dev environment.
    • B. Incorrect. A normal `dbt run` without `--empty` would execute the incremental merge logic, processing all rows to apply the new column. This is inefficient for schema validation and not a dry-run approach.
    • C. Incorrect. `dbt compile` only validates SQL syntax; it does not execute DDL or create database objects. Manually altering production tables bypasses dbt's schema management and is not idiomatic.
    • D. Incorrect. `--full-refresh` rebuilds the entire table with all data, which is unnecessary for validating a schema change. It defeats the purpose of avoiding a costly operation on millions of rows.

    Subdomain 1.13: Running models in sample mode using the --sample flag

    6.Which dbt command supports the --sample flag for running models in sample mode?(Select 2)

    1. A.dbt run
    2. B.dbt test
    3. C.dbt compile
    4. D.dbt build
    5. E.dbt docs generate
    Show answer & explanation

    Correct answers: A, Ddbt run; dbt build

    • A. Correct. The `--sample` flag is officially supported on `dbt run`, as documented in the dbt Developer Hub. Sample mode on `dbt run` allows you to process a time-based subset of data, reducing build times and warehouse costs during development and CI. It uses an `event_time` column configured on models to filter data by relative (e.g., '3 days') or static time specs.
    • B. Incorrect. The `--sample` flag is not available for `dbt test`. Sample mode is designed specifically for running models to build filtered datasets. Tests operate on existing data or schema and do not support the time-based sampling mechanism.
    • C. Incorrect. `dbt compile` does not support the `--sample` flag. The command compiles SQL without executing it, so there is no concept of data sampling. The `--sample` flag only applies to commands that actually run models, namely `dbt run` and `dbt build`.
    • D. Correct. The `--sample` flag is also supported on `dbt build`, as confirmed by official documentation and release notes (introduced in dbt Core v1.10). When used with `dbt build`, sample mode applies the time-based filter to models and their seeds/sources, helping validate the entire DAG with a subset of data while still running associated tests.
    • E. Incorrect. `dbt docs generate` does not support `--sample`. This command generates documentation artifacts from the manifest; it does not execute model logic, so sampling is irrelevant.

    Domain 1: Developing dbt models

    Subdomain 1.5: Creating a logical flow of models and building clean DAGs

    7.A developer needs to create a transformation that joins `stg_users` and `stg_transactions` to filter out test accounts. This filtered dataset is needed by three different downstream marts models. However, the developer does not want this intermediate dataset to create a view or table in the database to keep the warehouse clean. Which materialization configuration should be applied to this intermediate model?

    1. A.view
    2. B.table
    3. C.ephemeral
    4. D.incremental
    Show answer & explanation

    Correct answer: Cephemeral

    • A. Incorrect. The view materialization creates a persistent view object in the database schema. While views avoid physical storage, they still appear as objects in the warehouse, which does not meet the developer's requirement to avoid creating views or tables.
    • B. Incorrect. The table materialization creates a physical table in the database. This directly contradicts the requirement to keep the warehouse clean by avoiding intermediate database objects.
    • C. Correct. The ephemeral materialization inlines the model's logic directly into downstream queries as a Common Table Expression (CTE). Because dbt compiles this logic into the models that reference it, no physical table or view is ever created in the data warehouse, effectively keeping the warehouse clean.
    • D. Incorrect. Incremental materialization creates and maintains a persistent table that is updated with new data. This creates a permanent database object and storage footprint, violating the requirement to keep the warehouse free of intermediate views or tables.

    Subdomain 1.1: Identifying and verifying any raw object dependencies

    8.Review the following source configuration: ```yaml sources: - name: stripe tables: - name: charges freshness: warn_after: {count: 12, period: hour} error_after: {count: 24, period: hour} loaded_at_field: _batched_at ``` If the most recent record in the `charges` table has a `_batched_at` timestamp of 18 hours ago, what will be the result of running `dbt source freshness`?

    1. A.Pass
    2. B.Warn
    3. C.Error
    4. D.Skip
    Show answer & explanation

    Correct answer: BWarn

    • A. Incorrect. A "Pass" status requires the most recent record to be newer than the defined `warn_after` threshold. Since 18 hours exceeds the 12-hour warning threshold, the check will not pass.
    • B. Correct. dbt evaluates freshness by comparing the current time to the most recent value in the `loaded_at_field`. Because 18 hours is greater than the `warn_after` threshold (12 hours) but less than the `error_after` threshold (24 hours), dbt will return a 'Warn' status.
    • C. Incorrect. An "Error" status is only triggered when the record's age exceeds the `error_after` threshold. In this case, 18 hours has not yet reached the 24-hour error limit.
    • D. Incorrect. "Skip" would occur if the freshness check was not configured or if dbt was unable to find the specified field. Here, the source is properly configured with a `loaded_at_field`, so the check will execute and produce a result.

    Subdomain 1.6: Defining configurations in dbt_project.yml

    9.You are managing a dbt project named 'analytics'. You have a requirement that all models located in the `models/marts/finance` directory must be materialized as tables, while the rest of the project should default to views. Which configuration in `dbt_project.yml` correctly achieves this?

    1. A.models: analytics: +materialized: view marts: finance: +materialized: table
    2. B.models: analytics: materialized: view finance: materialized: table
    3. C.models: +materialized: view finance: +materialized: table
    4. D.configuration: models: analytics: marts: finance: type: table
    Show answer & explanation

    Correct answer: Amodels: analytics: +materialized: view marts: finance: +materialized: table

    • A. Correct. This configuration follows dbt's requirement to nest configurations under the 'models' key followed by the project name ('analytics'). It correctly uses the '+' prefix for the 'materialized' property to indicate it is a dbt configuration. It sets a project-wide default of 'view' and provides a specific override for the sub-directory path 'marts/finance' to use 'table'.
    • B. Incorrect. This option fails for two reasons: it omits the mandatory '+' prefix for configuration properties (e.g., '+materialized'), and it skips the 'marts' directory in the YAML hierarchy, which would prevent it from correctly targeting the models in 'models/marts/finance'.
    • C. Incorrect. Configurations in 'dbt_project.yml' must be scoped under the project name (in this case, 'analytics') to be applied correctly. Additionally, the 'finance' key is not properly nested under the 'marts' directory path as required by the file structure.
    • D. Incorrect. This option uses an invalid top-level key ('configuration') instead of the standard 'models' key. It also uses an unsupported property name ('type') instead of dbt's '+materialized' configuration property.

    Subdomain 1.9: Providing access to users to models with the "grants" config

    10.You are troubleshooting a `dbt run` failure. The error log shows: `Database Error: Insufficient privileges to GRANT ownership on table.` Your model config is: ```sql {{ config(grants={'select': ['reporter'], 'ownership': ['admin_role']}) }} ``` What is the most likely cause of this error?

    1. A.The `grants` config syntax is incorrect.
    2. B.The role executing `dbt run` does not have the permission to grant ownership to `admin_role`.
    3. C.The `admin_role` does not exist in the database.
    4. D.You cannot grant ownership via dbt configurations.
    Show answer & explanation

    Correct answer: BThe role executing `dbt run` does not have the permission to grant ownership to `admin_role`.

    • A. The `grants` config syntax shown is correct and follows the valid dbt pattern for declaring privileges within a dictionary. The error message specifically refers to a database permissions issue, not a Jinja or YAML parsing failure.
    • B. The error message explicitly states 'insufficient privileges to GRANT ownership', which occurs when the role executing dbt does not have the necessary authorization to transfer or grant ownership rights on the database object. In many data warehouses (like Snowflake), transferring ownership is a highly privileged operation that the standard dbt service role may not possess.
    • C. If the `admin_role` did not exist, the database would typically return a specific error stating that the role was not found. 'Insufficient privileges' refers to the capability of the role performing the action, not the existence of the target role.
    • D. dbt does support managing privileges, including ownership, through the `grants` configuration. The failure is not due to a lack of functionality in dbt, but rather a permissions restriction enforced by the underlying database on the role running the command.

    Subdomain 1.8: Creating Python Models

    11.You are developing a Python model in dbt to perform complex forecasting using the `prophet` library. You need to ensure this third-party package is available during execution. How should you configure this in the model file?

    1. A.import prophet inside the function definition without any configuration.
    2. B.Add `dbt.config(packages=['prophet'])` at the beginning of the model function.
    3. C.Add a `requirements.txt` file to the models directory.
    4. D.Use the `{{ config() }}` Jinja macro to install pip packages.
    Show answer & explanation

    Correct answer: BAdd `dbt.config(packages=['prophet'])` at the beginning of the model function.

    • A. Incorrect. Simply importing the library without configuration is insufficient. If the library is not already pre-installed in the target environment (e.g., Snowflake's Anaconda channel or Databricks runtime), the import will fail with a ModuleNotFoundError. dbt needs an explicit declaration to provision the environment.
    • B. Correct. In dbt Python models, the `dbt.config()` method is used within the Python model script (typically inside the `model(dbt, session)` function) to specify configurations. The `packages` parameter tells dbt which third-party libraries need to be installed or made available in the execution environment.
    • C. Incorrect. dbt does not automatically parse a `requirements.txt` file located in the models directory to manage dependencies for individual models. Configuration must be handled via the model's Python code or project-level settings.
    • D. Incorrect. The `{{ config() }}` Jinja macro is used in SQL models. Python models use the `dbt.config()` Python function call to configure settings like packages, materialized strategy, and tags.

    Subdomain 1.3: Conceptualizing modularity and how to incorporate DRY principles

    12.Your team has a complex dbt project with multiple staging models that extract JSON payloads. Currently, the JSON extraction logic is repeated in 15 different staging models. A junior engineer proposes creating a single intermediate model that unions all 15 raw tables, extracts the JSON, and then fans them back out into 15 separate models to keep the code DRY. Statement: This proposed architecture adheres to dbt's recommended modularity best practices because it centralizes the JSON extraction logic into a single model, thereby reducing code duplication.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: BFalse

    • A. The statement is false because while centralizing logic aims to reduce code duplication, the proposed 'union-then-fanout' architecture violates dbt's core modularity principles by merging unrelated sources into a single bottleneck model, which obscures data lineage and creates a single point of failure for 15 different downstream models.
    • B. The statement is false because dbt's recommended modularity best practices suggest using reusable macros for repeated logic like JSON extraction. This approach allows each staging model to remain independent and source-specific (maintaining clear 1:1 lineage) while still adhering to DRY principles in a maintainable, performant, and scalable way.

    Subdomain 1.4: Using commands such as build, run, test, docs, show, snapshot, and seed

    13.You have a singular test named `assert_total_revenue_is_positive.sql` that queries `fct_orders` using the `ref()` function. You recently updated the logic in `fct_orders` and want to run only this specific model and any tests attached to it. You execute the command `dbt run --select fct_orders` followed by `dbt test --select fct_orders`. Statement: The command `dbt test --select fct_orders` will execute all generic tests defined in the YAML file for `fct_orders`, but it will skip the singular test `assert_total_revenue_is_positive.sql` because singular tests must be selected by their file name directly.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: BFalse

    • A. The statement is false because dbt's selection logic is graph-aware; when a singular test uses the `ref()` function, it creates a dependency that allows dbt to include the test automatically when the referenced model is selected.
    • B. The statement is false because `dbt test --select <model_name>` includes all tests that depend on the specified model. This includes both generic tests defined in YAML files and singular tests located in the tests directory that use the `ref()` function to reference the model.

    Subdomain 1.2: Understanding core dbt materializations

    14.You are maintaining an incremental model `fct_page_views`. The source data occasionally includes late-arriving data (e.g., events from 3 days ago arriving today). Your current incremental logic only selects data where `event_time > (select max(event_time) from {{ this }})`. What will happen to the late-arriving data, and how should you fix it?

    1. A.The data will be duplicated because the incremental logic re-processes recent partitions to accommodate the late data. To fix this, you must specify a `unique_key` to allow dbt to update existing records.
    2. B.The data will be missed because its timestamp is lower than the max timestamp in the target. You should subtract a lookback window from the max timestamp in the WHERE clause.
    3. C.The data will be processed correctly because dbt's incremental materialization is designed for this. Its built-in logic automatically re-scans recent source partitions to capture any late-arriving events.
    4. D.The run will fail because inserting data with an older `event_time` violates the table's time-based partitioning scheme. The database rejects writes to older, closed-off partitions.
    Show answer & explanation

    Correct answer: BThe data will be missed because its timestamp is lower than the max timestamp in the target. You should subtract a lookback window from the max timestamp in the WHERE clause.

    • A. Incorrect. The current logic `event_time > max(event_time)` will exclude late-arriving records entirely, not duplicate them. While specifying a `unique_key` is important for deduplication when using a lookback window, it does not address the root cause of the data being missed.
    • B. Correct. Late-arriving records with an `event_time` older than the current maximum in the target table will be filtered out by the `> max(event_time)` logic. To capture this data, you must subtract a lookback window from the max timestamp in the WHERE clause to re-ingest recent history, and use a `unique_key` to ensure existing records aren't duplicated.
    • C. Incorrect. dbt's incremental materialization does not automatically handle late-arriving data; its behavior is defined by the SQL logic you provide. If your filter excludes older timestamps, dbt will not capture that data unless the logic is updated or a full-refresh is executed.
    • D. Incorrect. Late-arriving data will not cause a model run to fail; it will simply lead to data gaps. The issue is with the incremental logic, not with database partitioning constraints, and the run will complete without error.

    Subdomain 1.8: Creating Python Models

    15.A data engineer creates a Python model named `customer_churn.py`. When `dbt run` is executed, where is the Python code actually processed and executed?

    1. A.On the local machine where the dbt CLI is installed, using the system's Python runtime.
    2. B.On the dbt Cloud scheduler infrastructure, where a dedicated process runs the Python model.
    3. C.On the data platform (e.g., Snowflake, Databricks, BigQuery) infrastructure.
    4. D.On a separate EC2 instance managed by dbt Labs, which handles all Python model processing.
    Show answer & explanation

    Correct answer: COn the data platform (e.g., Snowflake, Databricks, BigQuery) infrastructure.

    • A. Incorrect. The local machine where the dbt CLI is installed handles orchestration, compilation, and communication with the adapter, but the Python model's code is not executed locally. Instead, dbt sends the Python logic to the data platform for execution.
    • B. Incorrect. dbt Cloud scheduler infrastructure manages job triggering and orchestration, but it does not run the Python model's processing. The actual execution is delegated to the data platform's compute environment.
    • C. Correct. Python models in dbt are executed on the data platform's infrastructure, such as Snowflake's Snowpark, Databricks' PySpark clusters, or BigQuery's Python environment. This ensures data processing occurs where the data resides, leveraging the platform's compute resources.
    • D. Incorrect. dbt Labs does not provide or manage separate EC2 instances for executing Python models. Compute is always handled by the data platform configured in the dbt profile, not by external infrastructure managed by dbt Labs.

    Subdomain 1.7: Using dbt Packages

    16.You have imported a marketing analytics package that contains several models. However, your business requirements dictate that one specific model from this package, `facebook_ads_spend`, should not be materialized in your warehouse. How can you disable this specific model without removing the package?

    1. A.Delete the `facebook_ads_spend.sql` model file from the `dbt_packages` directory to remove it.
    2. B.Add `enabled: false` for that specific model in your root `dbt_project.yml` file.
    3. C.Comment out the entire entry for the marketing analytics package within your `packages.yml` file.
    4. D.Run `dbt run --exclude facebook_ads_spend` for every job to prevent the model from materializing.
    Show answer & explanation

    Correct answer: BAdd `enabled: false` for that specific model in your root `dbt_project.yml` file.

    • A. Incorrect. Deleting files directly from the `dbt_packages` directory is not recommended because this folder is managed by dbt and will be overwritten the next time `dbt deps` runs. This approach is not maintainable and does not provide a reproducible solution.
    • B. Correct. Adding `enabled: false` for that specific model in your root `dbt_project.yml` file is the standard and most maintainable way to disable a single model from a package. This configuration overrides the package's default without affecting other models or requiring manual intervention.
    • C. Incorrect. Commenting out the entire entry for the marketing analytics package in `packages.yml` would prevent the whole package from being installed, removing all its models and macros. This does not meet the requirement of disabling only the `facebook_ads_spend` model while keeping the rest of the package.
    • D. Incorrect. Running `dbt run --exclude facebook_ads_spend` for every job requires manual intervention or specific CI/CD configuration each time, making it error-prone and inefficient. A configuration-based approach is more reliable and maintainable.

    Domain 2: Managing dbt models governance

    Subdomain 2.3: Defining constraints in YAML to enforce data integrity at the platform level

    17.A data engineer sets contract.enforced: true on an incremental model without defining all columns in the YAML schema. When they run dbt run, it completes successfully because incremental models do not enforce schema contracts.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: BFalse

    • A. The statement is false because incremental models do enforce schema contracts when contract.enforced is set to true, and omitting columns from the YAML causes the run to fail.
    • B. The statement is false because dbt enforces schema contracts on incremental models just like any other model; defining contract.enforced: true without all columns will cause the run to fail.

    Subdomain 2.3: Defining constraints in YAML to enforce data integrity at the platform level

    18.To enable constraint enforcement in dbt, you must set the ______ property to true in the model's YAML configuration.

    1. A.`contract.enforced`
    2. B.`constraints.enforce`
    3. C.`enforce_constraints`
    Show answer & explanation

    Correct answer: A`contract.enforced`

    • A. Correct. The `contract.enforced` property is used in the model's YAML configuration to enable constraint enforcement. When set to true, dbt enforces the defined constraints (e.g., not_null, unique) at the platform level, ensuring data integrity.
    • B. Incorrect. `constraints.enforce` is not a valid property in dbt's YAML configuration. The correct syntax uses the `contract.enforced` configuration key to enable constraint enforcement.
    • C. Incorrect. `enforce_constraints` is not a recognized property in dbt's YAML configuration. dbt uses a namespaced configuration approach, and the correct property for constraint enforcement is `contract.enforced`.

    Domain 2: Understanding dbt models governance

    Subdomain 2.2: Creating different versions of our models and deprecating the old ones

    19.You are preparing to release version 3 of `fct_sessions`. Version 2 is currently the `latest_version`. You want to merge the code for version 3 into the codebase so it is available for testing, but you do not want downstream models to use it by default yet. How should you configure the YAML?

    1. A.Set `latest_version: 3` but add `enabled: false` to version 3.
    2. B.Set `latest_version: 2` and define both v2 and v3 in the `versions` list.
    3. C.Do not add v3 to the `versions` list until it is ready to be the latest version.
    4. D.Set `latest_version: 3` and use `prerelease: true` for version 3.
    Show answer & explanation

    Correct answer: BSet `latest_version: 2` and define both v2 and v3 in the `versions` list.

    • A. Incorrect. Setting `latest_version: 3` would immediately make v3 the default for all unversioned `ref()` calls in downstream models. Adding `enabled: false` would disable the model version entirely, preventing it from being built or tested, which defeats the purpose of merging it for testing.
    • B. Correct. In dbt, the `latest_version` parameter determines which version is returned by an unversioned `ref()` call. By keeping `latest_version: 2`, existing downstream models will continue to use v2. Adding v3 to the `versions` list allows you to explicitly build and test v3 (e.g., using `ref('fct_sessions', version=3)`) without impacting production dependencies.
    • C. Incorrect. If version 3 is not added to the `versions` list in the YAML file, dbt will not recognize it as a valid version of the model. This makes it impossible to utilize dbt's built-in versioning and testing features for that specific model file.
    • D. Incorrect. dbt does not have a `prerelease` property for model versions. The primary mechanism for controlling version promotion is the `latest_version` property.

    Subdomain 2.1: Adding contracts to models to ensure the shape of models

    20.To guarantee that a model's output exactly matches the defined columns and data types before it is built in the data warehouse, you must configure the model with `_______` in your YAML file.

    1. A.contract: {enforced: true}
    2. B.enforce_contract: true
    3. C.schema: {strict: true}
    4. D.constraints: {enabled: true}
    Show answer & explanation

    Correct answer: Acontract: {enforced: true}

    • A. Correct. In dbt (v1.5 and later), model contracts are enabled by setting `contract: {enforced: true}` within a model's configuration. This tells dbt to validate that the model's SQL output exactly matches the columns and data types defined in the YAML file, failing the build if there is a discrepancy.
    • B. Incorrect. `enforce_contract: true` is not a valid configuration key in dbt. dbt uses a nested configuration block under the `contract` key.
    • C. Incorrect. `schema: {strict: true}` is not a valid dbt configuration for enforcing model shapes. Model governance and schema validation are handled through the `contract` block.
    • D. Incorrect. While dbt model contracts may implement physical constraints in the warehouse (like NOT NULL), they are not enabled using a `constraints: {enabled: true}` key. The correct configuration is `contract: {enforced: true}`.

    Domain 3: Debugging data modeling errors

    Subdomain 3.2: Troubleshooting using compiled code

    21.You are reviewing the compiled SQL for a model and notice excessive blank lines and indentation that make the code hard to read. The source Jinja looks like this: ```sql SELECT {% if is_incremental() %} column_a, {% endif %} column_b FROM table ``` What Jinja feature should be applied to the source code to clean up the whitespace in the compiled output?

    1. A.Use `{%-` and `-%}` for whitespace control.
    2. B.Use the `trim()` function on the SQL string.
    3. C.Enable the `pretty_print: true` config in `dbt_project.yml`.
    4. D.Remove the indentation in the source file.
    Show answer & explanation

    Correct answer: AUse `{%-` and `-%}` for whitespace control.

    • A. Correct. Jinja's whitespace control markers (`{%-` and `-%}`) allow you to strip whitespace and newlines from the start or end of a block. Applying these markers (e.g., `{%- if ... -%}`) trims the resulting compiled output, removing excessive blank lines while allowing the developer to maintain readable indentation in the source Jinja code.
    • B. Incorrect. While `trim()` is a common SQL function and a Jinja filter for strings, it does not control the rendering layout of the template itself. It cannot remove the literal newlines and spaces generated by the placement of Jinja tags in the file.
    • C. Incorrect. There is no global `pretty_print` configuration in `dbt_project.yml` that automatically cleans up whitespace generated by Jinja tags. Templating behavior is controlled at the code level using Jinja syntax.
    • D. Incorrect. While removing source indentation would reduce the space in the compiled output, it is poor practice as it makes the source code difficult for engineers to read and maintain. Whitespace control operators are the idiomatic solution for this problem.

    Subdomain 3.4: Developing and implementing a fix and testing it prior to merging

    22.You have identified a logic error in the `int_order_items` model. You have created a feature branch, fixed the SQL logic, and successfully ran the model in your development schema. What is the most appropriate next step to validate the fix before opening a Pull Request?

    1. A.Merge the changes into the main branch immediately to test in production.
    2. B.Run `dbt test --select int_order_items` to ensure the specific model meets assertions.
    3. C.Run `dbt seed` to refresh all static data.
    4. D.Delete the production table to ensure a clean rebuild.
    Show answer & explanation

    Correct answer: BRun `dbt test --select int_order_items` to ensure the specific model meets assertions.

    • A. Incorrect. Merging changes into the main branch immediately to test in production is a violation of the development lifecycle. This bypasses code review and CI/CD checks, potentially introducing errors into the production environment before they are verified.
    • B. Correct. After running the model, the next step is to execute `dbt test --select int_order_items`. This ensures that the model meets all defined assertions (such as uniqueness, non-null constraints, and custom business logic) in your development environment before you propose the change via a Pull Request.
    • C. Incorrect. Running `dbt seed` refreshes static data from CSV files. Unless your specific logic fix depends on updated seed data, this step does not validate the SQL transformations or logic changes made within the `int_order_items` model.
    • D. Incorrect. Manually deleting production tables is dangerous and unnecessary. dbt handles the creation and replacement of tables automatically. Validation should always be performed in a development or staging environment, never by manipulating production data directly.

    Subdomain 3.1: Understanding logged error messages

    23.During a dbt run, you receive the following error in your logs: `Database Error in model int_payments (models/staging/int_payments.sql) ... syntax error at or near "GROUP"`. You suspect a missing comma or trailing comma in the SELECT statement just before the GROUP BY clause. True or False: To pinpoint the exact line number of the syntax error as interpreted by the data warehouse, you should inspect the raw Jinja file (`models/staging/int_payments.sql`) rather than the compiled SQL file in the `target/run/` directory, because the database error line numbers correspond directly to the original Jinja file.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: BFalse

    • A. The statement is false because the data warehouse receives and executes the compiled SQL version of a model, not the raw Jinja template. Any line numbers provided in a database error message will align with the rendered code in the `target/run/` or `target/compiled/` directories, rather than the source file in the `models/` directory.
    • B. The statement is false because the Jinja compilation process—including macro expansion and the resolution of ref() or source() functions—frequently alters the line count and structure of the final query. Therefore, the compiled SQL in the `target/` directory is the only reliable reference for mapping warehouse error line numbers to the executed code.

    Subdomain 3.3: Troubleshooting .yml compilation errors

    24.An analytics engineer is refactoring a `schema.yml` file to reduce repetition. They define a YAML anchor for a standard set of column tests and descriptions as `&standard_audit_columns`. When applying this to a new model's columns, they receive a compilation error because they used standard YAML list syntax instead of the correct merge key. To successfully inject the anchor's dictionary into the column definition, they must use the ______ syntax.

    1. A.<<: *standard_audit_columns
    2. B.merge: *standard_audit_columns
    3. C.import: &standard_audit_columns
    4. D.include: *standard_audit_columns
    Show answer & explanation

    Correct answer: A<<: *standard_audit_columns

    • A. Correct. The syntax `<<: *anchor_name` is the standard YAML merge key syntax used to inject or merge the contents of a mapping referenced by an anchor into another mapping. In dbt's `schema.yml`, this allows engineers to inline standard tests or descriptions directly into column definitions.
    • B. Incorrect. The syntax `merge: *standard_audit_columns` is not valid YAML syntax for merging dictionaries. YAML only recognizes `<<` as the special merge key; using `merge` would create a literal key named 'merge' with the anchor content as its value, rather than flattening the dictionary.
    • C. Incorrect. This syntax uses `&`, which defines a new anchor, rather than `*`, which references an existing one. Furthermore, `import` is not a standard YAML merge operator and would not result in the desired dictionary injection.
    • D. Incorrect. `include` is not a standard YAML operator for dictionary merging. While some pre-processors or loaders use 'include' for file imports, standard YAML treats this as a literal key. It would place the aliased mapping as a nested value under the 'include' key rather than merging its fields into the current column definition.

    Subdomain 3.5: Managing dbt behavior with flags

    25.You are running a CI pipeline for a dbt project with state comparison. You use the command `dbt run --select state:modified --defer --state ./prod-artifacts`. The `--defer` flag in this command will cause dbt to rebuild all upstream models that were not explicitly selected.

    1. A.True
    2. B.False
    Show answer & explanation

    Correct answer: BFalse

    • A. The statement is false because the `--defer` flag does not rebuild upstream models; it tells dbt to resolve unselected upstream references against the state manifest (existing production relations), avoiding rebuilding them.
    • B. The statement is false because `--defer` defers unselected upstream models to the existing relations from the specified state, so they are not rebuilt. Only models that are explicitly selected via `state:modified` are built.

    Domain 4: Managing data pipelines

    Subdomain 4.2: Using dbt clone

    26.The `dbt clone` command is a critical component of workflows that use state comparison and deferral. Which dbt feature does `dbt clone` directly enable by providing the necessary database objects for unbuilt models?

    1. A.The `dbt docs generate` command.
    2. B.The `dbt source freshness` command.
    3. C.The `--defer` flag.
    4. D.The `dbt seed` command.
    Show answer & explanation

    Correct answer: CThe `--defer` flag.

    • A. Incorrect. `dbt docs generate` creates documentation by analyzing the manifest and catalog files; it does not rely on database objects created by `dbt clone` to function.
    • B. Incorrect. `dbt source freshness` is used to calculate the age of source data based on metadata or timestamps. It is independent of the `dbt clone` command.
    • C. Correct. The `--defer` flag allows dbt to resolve references to models not included in the current run by looking at a provided state manifest. `dbt clone` directly enables efficient state-based workflows by providing a mechanism to copy existing relations (clones) from a source environment into a target environment, ensuring all necessary database objects are present for unbuilt models.
    • D. Incorrect. `dbt seed` is a command used to load CSV files into the data warehouse as tables. It is a distinct data loading process and does not interact with or rely on `dbt clone`.

    Subdomain 4.1: Troubleshooting and managing failure points in the DAG

    27.You have configured a source with a freshness block. You want your pipeline to fail immediately if the source data is older than 24 hours, preventing any downstream models from processing stale data. Which command sequence achieves this?

    1. A.dbt run --fail-fast
    2. B.dbt source freshness dbt build --select source_status:fresher+
    3. C.dbt source freshness If exit code is 0, run dbt build
    4. D.dbt test --source
    Show answer & explanation

    Correct answer: Cdbt source freshness If exit code is 0, run dbt build

    • A. Incorrect. The `dbt run --fail-fast` command is designed to stop model execution as soon as the first model error occurs. It does not evaluate source freshness metadata or prevent a pipeline from starting based on data latency.
    • B. Incorrect. While `dbt source freshness` is the correct command to evaluate freshness, `source_status:fresher+` is not a standard dbt selection token. Furthermore, using a selector to filter models does not automatically enforce a hard failure of the entire pipeline; you must check the exit status of the freshness command to halt execution when thresholds are exceeded.
    • C. Correct. `dbt source freshness` evaluates the age of the data against the configured `error_after` thresholds. If any source is determined to be in an 'error' state (e.g., older than 24 hours), the command returns a non-zero exit code. Checking for an exit code of 0 before running `dbt build` ensures the pipeline fails immediately and prevents downstream models from processing stale data.
    • D. Incorrect. The `dbt test --source` command runs schema or data tests (like `unique` or `not_null`) defined on your sources. It does not check the metadata-based freshness blocks defined in your YAML configuration.

    Domain 5: Implementing dbt tests

    Subdomain 5.3: Implementing various testing steps in the workflow

    28.You are designing a workflow that ingests raw data from an external API. You want to ensure that the raw data meets basic freshness requirements (data is no older than 24 hours) before attempting to run any transformations. If the data is stale, the pipeline should stop immediately. Which sequence of commands is correct?

    1. A.dbt run dbt test
    2. B.dbt source freshness dbt build
    3. C.dbt test --select source:* dbt run
    4. D.dbt build --select source:*
    Show answer & explanation

    Correct answer: Bdbt source freshness dbt build

    • A. This sequence is incorrect because it runs transformations ('dbt run') before validating the data. Additionally, 'dbt test' executes schema and data tests, but it does not trigger the freshness checks defined in your YAML; only 'dbt source freshness' does that.
    • B. This is the correct sequence. 'dbt source freshness' explicitly checks the recency of source data against defined thresholds and returns a non-zero exit code if the data is stale, allowing the orchestrator to stop the pipeline. Following this with 'dbt build' ensures that if the data is fresh, models, tests, seeds, and snapshots are executed efficiently.
    • C. While 'dbt test --select source:*' runs schema tests (like unique or not_null) on source objects, it does not execute freshness checks. Therefore, the pipeline would proceed to 'dbt run' even if the data was older than 24 hours.
    • D. Selecting sources in a 'dbt build' command will run tests defined on those sources, but it does not execute the 'dbt source freshness' command. It fails to meet the requirement of stopping the pipeline specifically based on freshness metadata.

    Subdomain 5.1: Using generic, singular, custom, custom generic, and unit tests on a wide variety of models and sources

    29.You want to create a reusable test named `assert_valid_email` that checks if a column matches a specific regex pattern. You intend to apply this test to the `email` column in 10 different models via their YAML configurations. Which of the following is the correct way to define this custom generic test?

    1. A.Create a file `tests/assert_valid_email.sql` and use a Jinja loop to iterate over all models.
    2. B.Define a macro in `macros/test_assert_valid_email.sql` starting with `{% test assert_valid_email(model, column_name) %}`.
    3. C.Define a macro in `macros/assert_valid_email.sql` starting with `{% macro assert_valid_email(model, column_name) %}`.
    4. D.Add the regex logic directly into the `dbt_project.yml` under the `tests` key.
    Show answer & explanation

    Correct answer: BDefine a macro in `macros/test_assert_valid_email.sql` starting with `{% test assert_valid_email(model, column_name) %}`.

    • A. Incorrect. Placing a SQL file in the `tests/` directory creates a singular (data) test. While you can use Jinja within singular tests, they are not designed to be parameterized and reusable across multiple models via YAML configuration. Generic tests are the correct mechanism for this requirement.
    • B. Correct. In dbt, custom generic tests are defined using the `{% test <name>(model, column_name) %}` block. This syntax registers the logic as a test that can be applied to any column in a YAML file. These are typically stored in the `macros/` directory (or `tests/generic/` in modern dbt versions).
    • C. Incorrect. While generic tests are essentially macros, dbt requires the specific `{% test %}` block syntax to register the macro as a test. Using a standard `{% macro %}` block will define a functional macro, but dbt will not recognize it as a test that can be invoked via YAML declarations.
    • D. Incorrect. The `dbt_project.yml` file is for high-level project configurations, such as resource paths and materialization settings. It cannot store SQL test logic or regex patterns directly.

    Subdomain 5.3: Implementing various testing steps in the workflow

    30.Your team wants to implement Unit Tests in dbt to verify complex SQL logic using mock data before deploying to production. Unlike data tests, these should not query the actual data warehouse tables but rather use static inputs defined in YAML. What is the primary benefit of adding this step to your workflow?

    1. A.It ensures data freshness by validating source table load times against thresholds defined in the test's YAML.
    2. B.It validates the logic of the model transformation in isolation from production data anomalies.
    3. C.It automatically fixes SQL syntax errors by applying a pre-configured SQL linter to the model's compiled code.
    4. D.It replaces the need for `unique` and `not_null` tests by directly validating these constraints on the mock data.
    Show answer & explanation

    Correct answer: BIt validates the logic of the model transformation in isolation from production data anomalies.

    • A. Incorrect. Unit tests in dbt do not monitor data freshness. Freshness is measured by source freshness checks or schedules against live warehouse tables, whereas unit tests use static, mock data defined in YAML.
    • B. Correct. The primary benefit of unit tests is to validate the transformation logic in isolation. By using controlled, static inputs, you can ensure that the SQL logic produces the expected outputs regardless of anomalies or changing values in your actual production data. This helps catch logical bugs and edge cases early in the development cycle.
    • C. Incorrect. While running unit tests may surface SQL syntax or logic errors, dbt does not automatically fix these errors. Remediation requires manual intervention and code updates by the developer.
    • D. Incorrect. Unit tests complement but do not replace data quality tests like `unique` and `not_null`. These serve different purposes: unit tests validate the correctness of the transformation logic (the code), while data tests ensure data integrity and quality within the actual production environment (the data).

    Subdomain 5.2: Testing assumptions for dbt models and sources

    31.A team is ingesting raw data from a new source. They want to test that the primary key in a source table is never null. However, since the data quality from the source is still being evaluated, they want the test to raise a warning instead of an error upon failure. How should they configure this test in their `sources.yml` file?

    1. A.```yaml - name: id tests: - not_null config: severity: 'warn' ```
    2. B.```yaml - name: id tests: - not_null: severity: 'warn' ```
    3. C.```yaml - name: id tests: - not_null meta: severity: 'warn' ```
    4. D.```yaml - name: id tests: - not_null warn_if: '>0' ```
    Show answer & explanation

    Correct answer: B```yaml - name: id tests: - not_null: severity: 'warn' ```

    • A. Incorrect. Although the `config` key is a valid way to configure test settings in modern dbt, the YAML structure shown is invalid. The `config` key is not properly nested under `not_null`. As written, it creates two separate list items: a string `not_null` and an unrelated mapping with `config`, which does not attach the severity to the test. The correct syntax would be `- not_null: config: severity: 'warn'`.
    • B. Correct. This is the concise valid syntax for configuring a test severity. When the `not_null` test fails, dbt logs a warning instead of an error, allowing the pipeline to continue. This is the recommended approach per official dbt documentation for simple severity overrides.
    • C. Incorrect. The `meta` key is used to attach arbitrary metadata to a test, not to configure its behavior. Placing `severity` under `meta` has no effect on the test's severity; the test will still use the default severity of 'error'.
    • D. Incorrect. The `warn_if` configuration specifies a threshold for triggering a warning based on the number of failures, but it does not change the overall severity of the test. Without also setting `severity: 'warn'`, the test will still fail with an error when any nulls are present. This option does not fulfill the requirement of making the test raise a warning instead of an error.

    Domain 7: Implementing and maintaining external dependencies

    Subdomain 6.2: Implementing source freshness

    32.What is the primary purpose of the `dbt source freshness` command?

    1. A.To update the source data in the warehouse to the most recent version available.
    2. B.To validate that the data in source tables is not older than a defined threshold.
    3. C.To generate documentation for source tables, including their last loaded timestamp.
    4. D.To test the data quality of source tables by running custom data tests.
    Show answer & explanation

    Correct answer: BTo validate that the data in source tables is not older than a defined threshold.

    • A. Incorrect. The `dbt source freshness` command does not modify or update source data in the warehouse; it only inspects metadata or timestamps about source tables. Updating source data is handled by upstream ingestion processes (ETL/ELT), which are outside dbt's scope.
    • B. Correct. The primary purpose of `dbt source freshness` is to validate that the data in source tables is not older than specific thresholds (warn_after and error_after) defined in your sources.yml file. It calculates the age of the data based on a 'loaded_at' field or table metadata and reports the status.
    • C. Incorrect. While dbt documentation can display freshness results, generating documentation is the role of the `dbt docs generate` command. Freshness specifically evaluates the timeliness of data, not the production of documentation.
    • D. Incorrect. `dbt source freshness` is strictly focused on the recency of source data. General data quality checks, such as uniqueness or custom logic tests, are executed using the `dbt test` command.

    Subdomain 6.1: Implementing dbt exposures

    33.An analytics engineer has defined the following YAML configuration to document a downstream dashboard. However, when they run `dbt parse`, they receive a compilation error related to the exposure. What is the cause of the error? ```yaml version: 2 exposures: - name: executive_dashboard type: dashboard owner: name: 'Executive Team' email: 'exec@mycompany.com' depends_on: - 'mart_monthly_sales' ```

    1. A.The `type` must be one of `table` or `view`.
    2. B.The `owner` property requires a `slack` channel in addition to `name` and `email`.
    3. C.The dependency `'mart_monthly_sales'` must be wrapped in a `ref()` or `source()` macro.
    4. D.The `exposures:` key must be defined in the `dbt_project.yml` file, not a separate `.yml` file.
    Show answer & explanation

    Correct answer: CThe dependency `'mart_monthly_sales'` must be wrapped in a `ref()` or `source()` macro.

    • A. Incorrect. The `type` for an exposure can be any of the supported types: dashboard, analysis, notebook, application, machine_learning, or report. 'dashboard' is a perfectly valid type.
    • B. Incorrect. The `owner` block requires at least a `name` or an `email`. While `slack` is an optional field that can be included, it is not mandatory and its absence would not cause a compilation error.
    • C. Correct. In a dbt exposure's `depends_on` list, dbt expects references to models or sources to be wrapped in the `ref()` or `source()` macros. This allows dbt to resolve the dependency within the project's DAG. Providing a plain string like `'mart_monthly_sales'` will result in a compilation error.
    • D. Incorrect. Exposures are resources defined in YAML files within the project (typically alongside models), similar to sources or tests. They are not defined in the `dbt_project.yml` file.

    Domain 8: Leveraging the dbt state

    Subdomain 7.1: Understanding state and state selection

    34.An analytics engineer changes only the `description` of a model in its corresponding `.yml` properties file. No SQL or other configurations are altered. If they run `dbt build --select state:modified`, will this model be selected for the run?

    1. A.No, because a description change does not affect the compiled code or the data in the table.
    2. B.Yes, because any change to a model's properties file, including its description, is considered a modification.
    3. C.Only if the `dbt docs generate` command is run first.
    4. D.No, only changes to `tags` or `meta` configurations are considered modifications.
    Show answer & explanation

    Correct answer: ANo, because a description change does not affect the compiled code or the data in the table.

    • A. Correct. Changes to a node's description are considered documentation-only changes. dbt's state:modified logic ignores these because they do not impact the compiled SQL code, the execution logic, or the physical data in the target database. This ensures that documentation updates don't trigger unnecessary, costly re-runs of models.
    • B. Incorrect. Not every change to a properties file counts as a modification for state:modified. dbt specifically distinguishes between execution-relevant state (like SQL or config) and documentation-only state (like descriptions).
    • C. Incorrect. Running dbt docs generate updates the documentation site and catalog artifacts, but it does not influence how state:modified compares the current manifest to the previous state. The selection is driven by manifest differences, not documentation generation.
    • D. Incorrect. While it correctly suggests that description changes are not modifications, it is wrong to say that only tags or meta changes count. state:modified primarily detects changes in the compiled SQL (raw_code) and execution-relevant configurations (like materialized, database, schema, etc.).

    Subdomain 7.2: Using dbt retry

    35.An overnight dbt Cloud job running `dbt build` failed due to a transient network issue affecting a few ephemeral models. To re-run only the models and tests that failed or were skipped in the previous invocation without re-running successful nodes, you would execute the command `dbt ______`.

    1. A.retry
    2. B.run --select state:failed
    3. C.build --select result:error,result:skipped
    4. D.rerun --from-failure
    Show answer & explanation

    Correct answer: Aretry

    • A. Correct. Introduced in dbt Core v1.7, the `dbt retry` command is specifically designed to re-run the nodes (models, tests, etc.) that failed or were skipped during the previous dbt command execution. It automatically references the `run_results.json` from the target directory, making it the most efficient way to address transient failures without requiring the `--state` flag or specific selection syntax.
    • B. Incorrect. While `state:failed` is a valid selector for identifying failed nodes, it requires a `--state` flag to be passed to compare the current state against a prior state. Furthermore, the command `dbt run` would only execute models, meaning any tests that failed during the original `dbt build` invocation would be ignored.
    • C. Incorrect. dbt does not support a `result:` selector prefix. Selection based on previous execution outcomes is handled using the `state` method (e.g., `state:failed`, `state:skipped`) or the dedicated `dbt retry` command.
    • D. Incorrect. `rerun` is not a valid dbt CLI command. dbt uses either `dbt retry` or state-based selectors within standard commands (run, build, test) to handle re-executions of failed nodes.

    Want the full experience?

    These are just samples. Practice the full DBT Analytics Engineering question bank in quiz mode — free, no signup, with domain practice and exam simulation.