Design Your Data Quality Monitoring Requirements

Estimated read: 5 min

Section 6 proved the transformation logic is correct against known inputs. Section 5’s dq_check gates a single run’s quarantine rate against one fixed threshold. Neither answers a question a real data governance stakeholder actually asks: is data quality getting worse over time, and can anyone see that without writing SQL. This lecture designs what closes that gap.

What dq_check deliberately doesn’t do

Part 1, Section 10’s multi-task DAG lecture forward-referenced this exact section for a reason: dq_check makes one pass/fail decision per run, against a hardcoded 5% threshold, visible only in that run’s job logs. It can’t show whether clickstream’s quarantine rate has crept from 1% to 4% over three weeks – still under threshold every single day, so dq_check never fires, while the trend itself is exactly the kind of early warning a governance team wants to see before it crosses 5% and actually breaks something downstream.

Three signals, three different sources

Signal Source What it answers
Expectations SDP’s native event log Is pipeline-level plumbing healthy (nulls in metadata, malformed rows at bronze)
Quarantine counts bronze_*_quarantine tables (Section 2) How much data fails StepRight’s own business rules, and how that’s trending
Referential integrity The unknown_customer_id-style checks (Sections 2-3) Are foreign keys resolving – orphaned rows pointing at records that don’t exist

These aren’t three views of the same thing – they’re genuinely different failure modes. Expectations catch structural plumbing issues (a source stops sending _source_file metadata, say); quarantine counts catch StepRight’s own business-rule violations; referential checks catch a specific, especially damaging failure mode where an order references a customer that plain row-level validation would miss entirely, since the row itself looks perfectly well-formed.

Why this needs SDP’s native expectations at all, given Section 2 already built quarantine tagging

@dp.expect (bare, report-only – not _or_drop or _or_fail) logs pass/fail counts directly into the pipeline’s event log with zero extra infrastructure – no new table, no extra write. Layering a handful of lightweight, structural expectations onto bronze and silver tables gets a second, independent monitoring signal essentially for free, without touching StepRight’s existing tag_quality/tag_business_rules quarantine pattern (Sections 2-3) at all. The two mechanisms stay cleanly separated by purpose: quarantine tagging still owns every business-rule decision this project cares about (that logic is unit-tested, in production, and does real routing); expectations exist purely to widen what the event log can tell a monitoring dashboard, report-only and non-blocking by design.

Design decision: a dq_ views layer, not raw table queries from the dashboard

Every dashboard visualization Lecture 4 builds queries a small set of purpose-built SQL views – dq_expectations_summary, dq_quarantine_summary, dq_referential_orphans – rather than querying bronze_*_quarantine or the event log directly from each chart. A dashboard built straight against raw tables means every visualization re-derives the same aggregation logic independently, and any schema change to a bronze table risks silently breaking a chart nobody remembers depends on it. A views layer is the one place that logic lives, tested and readable on its own, the same separation-of-concerns instinct Section 6 applied to transformation code, applied here to reporting queries instead.

What’s out of scope

This section monitors and alerts – it does not auto-remediate. A quarantine rate crossing an alert threshold (Lecture 5) notifies a human; it doesn’t automatically retry, backfill, or patch bad data. That boundary is deliberate: automatic remediation of a data quality problem risks silently masking the exact issue someone needs to actually investigate.

Who actually looks at this

dq_check’s pass/fail lives in the Jobs UI, a place engineers look. This section’s dashboard is built for a different audience – a data governance stakeholder, an operations lead, or a merchandising analyst who has no reason to ever open the Jobs UI, but who does want a five-second answer to “is our data healthy this week” without asking an engineer to run a query for them. That audience shift is a real design constraint, not just a nice-to-have: it’s what pushes Lecture 4 toward visual charts over raw tables, and Lecture 5 toward a notification landing somewhere that audience actually watches, rather than another job-log entry only engineers would ever see.

The legacy-world equivalent

A legacy warehouse team solved the same problem with a hand-maintained data quality scorecard – often a spreadsheet, refreshed manually or by a scheduled export, tracking row counts and reject rates week over week because no built-in mechanism surfaced that history automatically. Everything this section builds replaces that spreadsheet with something that updates itself: the event log populates as a side effect of every pipeline run, the dq_ views compute directly against live tables, and the dashboard queries those views on its own refresh schedule – nobody has to remember to update anything by hand.

What’s next

Lecture 2 adds the lightweight @dp.expect constraints this design calls for and shows how to query their results from the event log. Lecture 3 builds the three dq_ views. Lecture 4 turns them into an actual dashboard. Lecture 5 closes the loop with alerting.


| ← Previous: StepRight - Data Quality Monitoring | Next: Setup Pipeline Event Logs for Expectations Monitoring → | |:—|—:|


Back to top

Independent, self-authored Databricks companion notes.

This site uses Just the Docs, a documentation theme for Jekyll.