Databricks

Lakeflow Declarative Pipelines Expectations Design Guide: Quality Monitoring & Invalid Data Handling

2026-03-21
更新: 2026-03-27
NicheeLab Editorial Team

Expectations in Lakeflow Declarative Pipelines (formerly Delta Live Tables / DLT) are a declarative way to validate and control data quality inside a pipeline. You embed rules like "this column must not be NULL" or "amount must be non-negative" directly in the table definition, and choose whether violating records are logged, dropped, or whether the entire pipeline should fail.

This article walks through the 3 operating modes of Expectations, both SQL and PySpark syntax, the quarantine pattern, quality monitoring via the event log, and how Expectations compare to Delta Table Constraints (NOT NULL / CHECK).

The 3 Operating Modes of Expectations

Expectations come in 3 modes that differ in how violating records are handled. You pick a mode based on the nature of the pipeline (batch vs. streaming) and business requirements (how much data loss is acceptable).

ModeBehavior on violationEffect on output tablePipeline continues?Typical use case
EXPECT (log)Records violations but still writes them to outputAll records writtenContinuesQuality monitoring, early-stage visibility
EXPECT OR DROP (drop)Excludes violating records from outputOnly passing records writtenContinuesFiltering bad data, building Silver tables
EXPECT OR FAIL (fail)A single violation stops the pipelineTransaction is rolled backStopsGold tables, billing data, anything that cannot tolerate gaps

EXPECT mode is the right choice when you do not want to stop the pipeline on violations but still want to track their count. A typical use case is initial Bronze-layer ingestion, where you monitor violation trends via the event log.

SQL Syntax: Defining Expectations with CONSTRAINT

To define Expectations in SQL, you use the CONSTRAINT clause inside a CREATE OR REFRESH statement. Quality rules are declared inline as part of the table definition.

-- EXPECT: 違反を記録するが全レコードを出力に含める
CREATE OR REFRESH MATERIALIZED VIEW silver_orders
(
  CONSTRAINT valid_amount EXPECT (amount > 0),
  CONSTRAINT not_null_id EXPECT (order_id IS NOT NULL)
)
AS SELECT * FROM LIVE.bronze_orders;

-- EXPECT OR DROP: 違反レコードを出力から除外
CREATE OR REFRESH MATERIALIZED VIEW silver_orders_clean
(
  CONSTRAINT valid_amount EXPECT (amount > 0) ON VIOLATION DROP ROW,
  CONSTRAINT not_null_id EXPECT (order_id IS NOT NULL) ON VIOLATION DROP ROW
)
AS SELECT * FROM LIVE.bronze_orders;

-- EXPECT OR FAIL: 1件でも違反があればパイプラインを停止
CREATE OR REFRESH MATERIALIZED VIEW gold_revenue
(
  CONSTRAINT valid_amount EXPECT (amount > 0) ON VIOLATION FAIL UPDATE
)
AS SELECT region, SUM(amount) AS total FROM LIVE.silver_orders_clean
GROUP BY region;

CONSTRAINT names must be unique within the pipeline. Since the event log uses these names as the key for tracking violation counts, business-meaningful names like valid_amount or not_null_customer_id are recommended.

PySpark Syntax: The @dlt.expect Decorator

In PySpark, Expectations are defined via decorators. In practice, the @dlt.expect_all family is most commonly used because it accepts multiple rules as a dictionary.

import dlt
from pyspark.sql.functions import col

# 単一条件の EXPECT(記録のみ)
@dlt.table
@dlt.expect("valid_amount", "amount > 0")
@dlt.expect("not_null_id", "order_id IS NOT NULL")
def silver_orders():
    return dlt.read_stream("bronze_orders")

# 複数条件をまとめて DROP
quality_rules = {
    "valid_amount": "amount > 0",
    "not_null_id": "order_id IS NOT NULL",
    "valid_region": "region IN ('APAC','EMEA','NA')"
}

@dlt.table
@dlt.expect_all_or_drop(quality_rules)
def silver_orders_clean():
    return dlt.read_stream("bronze_orders")

# FAIL: 1件でも違反でパイプライン停止
@dlt.table
@dlt.expect_all_or_fail({"positive_revenue": "total > 0"})
def gold_revenue():
    return (
        dlt.read("silver_orders_clean")
        .groupBy("region")
        .agg({"amount": "sum"})
        .withColumnRenamed("sum(amount)", "total")
    )

@dlt.expect_all takes a dictionary and applies every rule in EXPECT (log) mode. @dlt.expect_all_or_drop and @dlt.expect_all_or_fail correspond to DROP and FAIL modes respectively. Extracting the dictionary into an external variable makes rule management and test-time substitution much easier.

Quarantine Pattern: Isolating Violating Data for Later Processing

EXPECT OR DROP makes records disappear, and EXPECT lets bad data flow downstream. When you want to keep violating data but prevent it from reaching downstream tables, use the quarantine table pattern.

import dlt
from pyspark.sql.functions import expr

@dlt.table(comment="品質条件を満たすレコードのみ")
def silver_orders_valid():
    return (
        dlt.read_stream("bronze_orders")
        .filter("amount > 0 AND order_id IS NOT NULL")
    )

@dlt.table(comment="品質違反レコードを隔離")
def silver_orders_quarantine():
    return (
        dlt.read_stream("bronze_orders")
        .filter("amount <= 0 OR order_id IS NULL")
        .withColumn("quarantine_reason",
            expr("""CASE
                WHEN amount <= 0 THEN 'invalid_amount'
                WHEN order_id IS NULL THEN 'null_order_id'
                ELSE 'unknown'
            END"""))
    )

Adding a violation-reason column to the quarantine table makes it useful for data quality reporting, root-cause analysis by ops teams, and reinjection workflows after the data is fixed.

Reviewing Quality Metrics in the Event Log

Expectations violation counts are recorded automatically in the pipeline event log. You can see them on the pipeline detail page in the UI, or query the event_log table directly with SQL.

SELECT
  details:flow_progress.data_quality.expectations.name AS expectation_name,
  details:flow_progress.data_quality.expectations.dataset AS dataset,
  details:flow_progress.data_quality.expectations.passed_records AS passed,
  details:flow_progress.data_quality.expectations.failed_records AS failed,
  timestamp
FROM event_log(TABLE(my_catalog.my_schema.my_pipeline))
WHERE event_type = 'flow_progress'
  AND details:flow_progress.data_quality IS NOT NULL
ORDER BY timestamp DESC;

This query returns the pass and fail counts for each Expectation over time. Combine it with alerting on sudden spikes in violation rates to catch upstream data-quality regressions early.

Choosing Between Expectations and Delta Constraints (NOT NULL / CHECK)

DLT Expectations and Delta Table Constraints both relate to data quality, but they operate at different layers and behave differently.

AspectDLT ExpectationsDelta Constraints (NOT NULL / CHECK)
Where it appliesIn-pipeline data flow inside DLTAt write time to a Delta table
How it's definedCONSTRAINT clause / @dlt.expect decoratorALTER TABLE ADD CONSTRAINT
Violation optionsThree modes: log, drop, failWrite error (rejection) only
Metrics captureAutomatically recorded in the event logNone (error logs only)
Usable outside DLT?No (DLT pipelines only)Yes (applies to ordinary Spark writes too)
Typical purposeMonitoring and filtering quality at intermediate pipeline stagesSchema guard on the final table

In practice, the robust pattern is to use DLT Expectations to check quality progressively through the pipeline, then place Delta Constraints on the final Gold table so that only data that has cleared every quality check can be written.

Design Guidelines: Placement in the Medallion Architecture

  • Bronze: use EXPECT (log only) to visualize raw-data quality trends. Do not drop or fail.
  • Silver: use EXPECT OR DROP to filter out bad records. Route to a quarantine table when retention is needed.
  • Gold: use EXPECT OR FAIL to guarantee zero quality violations. Apply to billing and aggregation tables.

This staged quality gating minimizes the risk of upstream quality issues propagating downstream, while preventing data loss at the Bronze layer.

What Gets Tested on the Exam

  • Can you precisely distinguish the violation behavior of the 3 modes (EXPECT / EXPECT OR DROP / EXPECT OR FAIL)?
  • What happens to records dropped by EXPECT OR DROP (they are not auto-retained — quarantine must be implemented yourself)
  • How to retrieve pass and fail counts for Expectations from the event log
  • The difference in where Delta Constraints apply (in-pipeline vs. at table write time)

Check Your Understanding

Data Engineer Associate / Professional

問題 1

On a DLT pipeline Silver table, you want to exclude records where amount <= 0 from the output and track the violation count in the event log. The pipeline must not stop on violations. Which is the most appropriate approach?

  1. Define an EXPECT constraint amount > 0 with no ON VIOLATION clause
  2. Define an EXPECT constraint amount > 0 with ON VIOLATION DROP ROW
  3. Define an EXPECT constraint amount > 0 with ON VIOLATION FAIL UPDATE
  4. Add a CHECK constraint (amount > 0) to the Silver table via ALTER TABLE

正解: B

EXPECT ... ON VIOLATION DROP ROW excludes violating records from the output while letting the pipeline continue, and the violation count is recorded in the event log. EXPECT alone (A) still writes every record to the output. FAIL UPDATE (C) stops the pipeline. The CHECK constraint (D) is a Delta table constraint, not a DLT pipeline feature, and does not emit quality metrics to the event log.

Frequently Asked Questions

Where do records dropped by EXPECT OR DROP go? Can they be recovered?

Records dropped by EXPECT OR DROP are not written to the output table and are not automatically retained by default. Only the dropped-row count is captured in the event log. To make them recoverable, you need to implement a quarantine pattern yourself by routing violating records to a separate table.

Where can I see Expectations violation metrics?

They are recorded in the DLT pipeline event log (event_log). The flow_progress.data_quality.expectations field exposes the name, passed count, and failed count for each Expectation. You can also see them as charts on the pipeline detail page in the UI.

Can I combine Expectations with Delta Constraints?

Yes, they work well together. Expectations validate quality during the in-pipeline data flow, while Delta Constraints (NOT NULL / CHECK) enforce rules at table write time. A robust design uses Expectations for soft monitoring and Delta Constraints on the final table as a hard guard.

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Databricks

Databricks Certifications: All 7 Exams, Difficulty & Study Plan (2026)

Complete guide to all 7 Databricks certifications — Data Eng...

Databricks

Databricks Exam Difficulty Ranking: All 7 Certs Compared (2026)

Every Databricks certification ranked by difficulty, with st...

Databricks

Databricks Study Guide: Fastest Pass Route & Time Estimates (2026)

How to pass Databricks certifications efficiently. Official ...

Databricks

Databricks Data Engineer Associate: Complete Guide (2026)

Domain-by-domain breakdown of the Databricks Certified Data ...

Databricks

Databricks Data Engineer Professional: Complete Guide (2026)

Tactics for the Databricks Certified Data Engineer Professio...

Browse all Databricks articles (110)
© 2026 NicheeLab All rights reserved.