Scenario 2

Extending an Existing Model with a New Source

Add columns from a Fivetran-synced source to an existing intermediate model without breaking downstream consumers. Six prompts. Three interchangeable paths.

Path A walkthrough: extend int_customer_order_summary with retail.RET_TICKETS at the customer grain.

Path B walkthrough: extend int_orders_enriched with retail.RET_TICKETS at the order grain. Same source as Path A, different model and grain.

Path C walkthrough: extend int_product_sales_summary with retail.RET_PRODUCT_REVIEWS at the product grain.

Background

The scenario

An existing intermediate model is missing data needed for a follow-up question. The source already exists in Snowflake (Fivetran-synced) but isn't referenced by the model.

Steps: locate the target model and downstream consumers, find an unused source, validate grain and coverage, modify the target model with a LEFT JOIN, compile the downstream lineage, materialize.

Paths

Pick a path

Pick one path before Step 1. The prompt flow is identical across paths; only the placeholders change. All three can be run simultaneously in the room.

Path A

Customer 360 + Support Tickets

Target model
int_customer_order_summary
New source
retail.RET_TICKETS
Entity
customer
New columns
open_tickets_count, last_ticket_status, last_ticket_opened_at
Path B

Orders + Support Tickets

Target model
int_orders_enriched
New source
retail.RET_TICKETS (at order grain)
Entity
order
New columns
ticket_count, has_open_ticket_flag, last_ticket_status
Path C

Product Performance + Reviews

Target model
int_product_sales_summary
New source
retail.RET_PRODUCT_REVIEWS
Entity
product
New columns
avg_rating, review_count, low_rating_count (1-2 stars)
Paths A and B both use RET_TICKETS at different grains. The source is new to the target model, not new to the project.
Prompts

Prompts, in order

The prompts use placeholders. Substitute values for the path you picked. The placeholder table is below.

  1. Locate the target model

    Identify the target model, its grain, and its downstream consumers before editing.

    Find [TARGET_MODEL] in this project. Show me what it currently produces, its grain, and which models depend on it downstream.

    Then ask what unused sources are available.

    Find every source in this project related to [ENTITY] that [TARGET_MODEL] does NOT currently reference. I want to know what data is sitting in our warehouse that we're not using yet.
    Exercises: search, describe, lineage
  2. Discover the unused source

    dbt Wizard surfaces a configured source that isn't referenced by the target model.

    Describe the schema of [NEW_SOURCE]. Show me the columns, their types, the grain, and which column joins back to [ENTITY].
    Exercises: status, search, source-vs-model cross-referencing
  3. Validate the join

    Verify grain, coverage, and join-key match before writing SQL. Catches name-matching keys that don't actually align by data.

    Run a quick check: count rows in [NEW_SOURCE], count distinct join keys, and count how many of those keys match an [ENTITY] already in [TARGET_MODEL]. Tell me whether the grain is one-to-one or one-to-many.
    If the grain is many-rows-per-[ENTITY], decide whether to aggregate (open tickets count, review count) or pick the latest row by timestamp (last ticket status) before Step 4.
    Exercises: describe, warehouse, join-key inspection
  4. Modify the existing model

    Edit the existing model file. Do not create a new file.

    Update [TARGET_MODEL] to add [NEW_COLUMNS] from [NEW_SOURCE]. Use a LEFT JOIN so [ENTITY] rows without a match still appear, and aggregate [NEW_SOURCE] to one-row-per-[ENTITY] before joining if its grain is many-to-one. Preserve every column the model currently emits - only add new columns at the end.
    Required. LEFT JOIN, not INNER (INNER drops [ENTITY] rows without a match). Preserve existing columns - downstream consumers select specific columns by name, so renaming or removing them is a contract break.
    Exercises: file edits on the existing model
  5. Compile downstream and preview

    Compiling the downstream models confirms no consumer breaks on a renamed or removed column.

    Compile [TARGET_MODEL] and every downstream model that depends on it. Then preview 20 rows of [TARGET_MODEL] ordered deterministically. Do not materialize anything.
    Confirm: new columns populate for matched rows and null (not error) for unmatched. Total row count of [TARGET_MODEL] is unchanged. Every downstream model compiles.
    Exercises: dbt_compile across lineage, dbt_show on target
  6. Materialize

    Build into your dev schema. Step 5 already validated output and downstream compile; verification is scoped out for this timed lab.

    Materialize [TARGET_MODEL] into my dev schema. Skip the verification pass - the preview and downstream compile already confirmed the output.
    Exercises: dbt_run against dev schema

Placeholder substitutions

Path A

Customer 360

[TARGET_MODEL]
int_customer_order_summary
[NEW_SOURCE]
retail.RET_TICKETS
[ENTITY]
customer
[NEW_COLUMNS]
open_tickets_count, last_ticket_status, last_ticket_opened_at
Path B

Operations

[TARGET_MODEL]
int_orders_enriched
[NEW_SOURCE]
retail.RET_TICKETS
[ENTITY]
order
[NEW_COLUMNS]
ticket_count, has_open_ticket_flag, last_ticket_status
Path C

Merchandising

[TARGET_MODEL]
int_product_sales_summary
[NEW_SOURCE]
retail.RET_PRODUCT_REVIEWS
[ENTITY]
product
[NEW_COLUMNS]
avg_rating, review_count, low_rating_count
Result

What gets built

[TARGET_MODEL] emits [NEW_COLUMNS] from [NEW_SOURCE] in your dev schema. Existing column contract preserved, downstream models compile, row count matches the pre-edit baseline.
Next

References and next scenario

GitHub

Open SKILL.md

Skill definition with all three paths and instructor notes.

Reference

Printable prompt sheet

Every prompt in this scenario, formatted for print.

Next

Scenario 3

Activity layer plus segment model for VIPs, big spenders, and category-loyal customers.