dbt Sources and Freshness
Name the raw world once, monitor it forever
dbt sources declare where raw data lives, so models can read it with source() and dbt can check that it keeps arriving. Freshness checks turn 'the pipeline died' into an alert on the right page.
What you will learn
- Declare a source and its tables in YAML
- Read source tables in models with source()
- Configure freshness thresholds and run source freshness
What is this?
A dbt source is a declared view of a raw table (or a whole source system) in YAML. Models read sources with source('raw', 'orders') instead of hard-coded names, and dbt tracks their freshness: how recent the newest loaded_at row is, compared to warn and error thresholds.
Why do you need it?
- Declaring sources separates raw reality from your cleaned models.
- Freshness turns silent upstream stalls into paged alerts.
- source() keeps the dependency graph honest — lineage includes the raw world.
Mental model
A labeled crate from the supplier
A dbt source
The crate (source) is declared, labeled with its freshness, and the kitchen never worries about what is inside — they just call the crate's name.
How it works
- Declare source schema: name, tables, columns, and loaded_at_field.
- Reference with source('name', 'table') in model SQL.
- dbt source freshness queries max(loaded_at_field) and compares to thresholds.
- Warn and error alerts fire on freshness breaches in CI or scheduled runs.
Sources feed models and freshness checks watch their pulse.
In production
- The nightly revenue pipeline alerts when the orders source stops updating.
- A new analyst sees staging models back-linked to real raw tables via lineage.
- Freshness thresholds differ per system: payments strict, CRM lenient.
Best practices
- Declare every raw table you consume so nothing is read unadvertised.
- Pick loaded_at_field as the earliest reliable arrival timestamp.
- Set warn tight and error loose, and page owners by freshness threshold.
Common mistakes
- Hard-coding the raw schema.table name in models instead of source().
- Setting freshness on a field that is not the load timestamp, so reports look stale.
- Forgetting to schedule dbt source freshness to actually run.
Debugging tips
- If freshness warns daily, the loaded_at field may not be the ingestion timestamp.
- If source() fails, the source name or table is missing from the YAML definition.
Interview checkpoint
Hands-on lab
- Declare the raw source and its tables in YAML
- Rewrite a model to use source()
- Configure and run freshness checks
Declare Sources and Watch Freshness
30 min · intermediate
Quick quiz
Reading a raw table in dbt is done via
Freshness checks query the