Introduction
Welcome back! In our last lesson, we focused on building the Bronze layer of the Medallion Architecture. You learned how to implement robust ingestion patterns using Auto Loader and COPY INTO to reliably land raw data in your lakehouse.
Now that our raw data is captured, it's time to refine it. This lesson addresses the next crucial step in our data modeling journey: transforming and cleansing data for the Silver layer using quality rules. The Silver layer is where data engineering principles are applied to turn raw, sometimes messy, data into a reliable, conformed, and query-ready asset. We will focus on using Databricks' declarative tools to apply transformations and, most importantly, enforce data quality using expectations.
The Purpose of the Silver Layer
Before we write any code, let's solidify our understanding of the Silver layer's role. While the Bronze layer is an immutable archive of source data, the Silver layer serves as the cleansed, validated "single source of truth."
Think of it this way: if a data analyst or scientist needs customer data, they shouldn't have to query the raw bronze tables and perform the same cleaning steps every time. The Silver layer provides them with a trusted starting point.
Medallion Architecture: A Complete Guide
This article from a GAP Data Engineer provides excellent context on the design principles of the Silver layer. It reinforces why this layer is critical and shouldn't be skipped.
Please read the sections titled 'The Silver Layer: Cleansed and Conformed' and 'Mistake Deep Dive: Skipping Silver'. Focus on the design principles: what makes a good Silver table? Why is it a bad practice to put cleaning logic directly into the Gold layer?
Common transformations you'll perform when moving data from Bronze to Silver include:
- Type Casting: Converting strings to dates, timestamps, or numeric types.
- Column Manipulation: Splitting a
full_namecolumn intofirst_nameandlast_name, or combining fields. - Handling Nulls: Applying business rules to null values, such as replacing them with defaults.
- Standardization: Ensuring consistent formats for things like addresses, country codes, or currency.
Enforcing Data Quality with Expectations
A core responsibility of the Silver layer is to enforce data integrity. In Databricks, the modern and declarative way to do this is with Delta Live Tables (DLT), now integrated into a broader feature set called Lakeflow. DLT allows you to define data quality rules, called expectations, directly in your pipeline.
When a record fails to meet an expectation, you can configure one of three outcomes:
- Warn (Default): The record is still included in the target table, but the failure is logged in the pipeline's event log. This is useful for tracking data quality without dropping data.
- Drop: The record that fails the rule is discarded and not written to the target table. This is the most common action for cleansing data.
- Fail: The entire pipeline update stops immediately upon encountering a single failing record. This is reserved for critical data errors that signal a major upstream problem and require immediate intervention.

Implementing Silver Layer Transformations
Let's get hands-on. DLT pipelines can be defined using both SQL and Python, giving you the flexibility to use the language you're most comfortable with. Your experience with both languages will be valuable here.
The following resource from the official Databricks documentation provides concise examples for creating a cleansed, Silver-layer table from a bronze source.
Tutorial: Build an ETL pipeline using change data capture
This tutorial provides excellent, self-contained code snippets for creating a Silver table with data quality rules in both Python and SQL.
Navigate to 'Step 4: Cleanup and expectations to track data quality'. Review the code blocks for both Python and SQL. Notice the syntax for defining expectations and the action to take on violation (expect_all_or_drop in Python, ON VIOLATION DROP ROW in SQL).
Let's break down those implementation patterns.
SQL Implementation
In SQL, you define expectations using CONSTRAINT clauses within your CREATE OR REFRESH STREAMING TABLE statement. This approach is very readable and feels natural for those with a strong SQL background.
-- This DLT SQL code creates a silver table from a bronze source stream.
-- It applies two quality rules, dropping any rows that violate them.
CREATE OR REFRESH STREAMING TABLE silver.customers_clean (
-- Rule 1: The customer ID must not be null.
CONSTRAINT valid_id EXPECT (id IS NOT NULL) ON VIOLATION DROP ROW,
-- Rule 2: The operation type must be one of the expected values.
CONSTRAINT valid_operation EXPECT (operation IN ('APPEND', 'DELETE', 'UPDATE')) ON VIOLATION DROP ROW
)
COMMENT "Cleansed customer data from the bronze layer with quality checks."
AS
SELECT
id,
firstname,
lastname,
email,
address,
operation,
-- Cast the operation_date from string to timestamp for the silver layer
CAST(operation_date AS TIMESTAMP) as operation_date
FROM STREAM(bronze.customers_cdc_bronze);
Python Implementation
In Python, you use decorators (@dlt.expect, @dlt.expect_or_drop, @dlt.expect_or_fail) to attach quality rules to the function that defines your table. This allows for modularity and integrates well with more complex PySpark transformations.
import dlt
from pyspark.sql.functions import *
# This DLT Python code defines the same silver table.
# Notice how transformations like adding a new column are done with standard PySpark.
@dlt.create_streaming_table(
name="customers_clean",
comment="Cleansed customer data from the bronze layer with quality checks."
)
@dlt.expect_or_drop("valid_id", "id IS NOT NULL")
@dlt.expect_or_drop("valid_operation", "operation IN ('APPEND', 'DELETE', 'UPDATE')")
def customers_clean():
return (
dlt.read_stream("customers_cdc_bronze")
.withColumn("operation_date", col("operation_date").cast("timestamp"))
.withColumn("full_name", concat_ws(" ", col("firstname"), col("lastname")))
)
A Practical Walkthrough
Now, let's watch a video that puts all these concepts together in an end-to-end scenario. This will show you how these transformations and quality checks are applied in a real pipeline.
Build a Medallion Architecture with Databricks Lakeflow | Data Quality, Aggregation & Orchestration
This video by Thomas Hass provides a great demonstration of building a Silver layer using Databricks' declarative pipelines. It covers common cleaning tasks and the implementation of data quality rules.
Watch the following segments to see these concepts in action: Date Type Transformation (04:44 - 05:29): A classic Bronze-to-Silver task. Notice how string-formatted dates are converted to a proper date type. Defining and Applying Expectations (05:16 - 08:51): This is the core segment. Pay close attention to the syntax for expect all (warn), expect all or drop, and expect all or fail. Other Cleaning Examples (11:44 - 13:41): See how other transformations, like ensuring positive values with abs() and splitting a name column, are implemented.
Monitoring Data Quality in Production
Defining quality rules is only half the battle. In a production environment, you need to monitor the results. The DLT UI provides a great visual summary, but for automated monitoring and alerting, you need programmatic access to the quality metrics. DLT records all pipeline events, including data quality statistics, to an event log, which is itself a Delta table that you can query.
30 DLT Data Quality & Expectations | Monitor DLT pipeline using SQL | Define DQ rule |Observability
This video from Ease With Data demonstrates how to go beyond the UI and monitor your data quality by directly querying the DLT event log.
Please watch the segment 'Query DLT event logs using SQL' (14:32 - 17:18). This demonstrates how you can use simple SQL queries against the event log to build powerful monitoring dashboards and alerts for your data quality rules. This is a key skill for a professional data engineer.
By querying the event log, you can track the number of records dropped over time, identify which rules are failing most often, and set up alerts if the failure rate exceeds a certain threshold.
Conclusion
In this lesson, we bridged the gap between the raw Bronze layer and the cleansed Silver layer. You learned how to apply critical transformations and enforce data integrity using the declarative expectations feature in Delta Live Tables.
Key Takeaways:
- The Silver layer is the single source of truth for cleansed, conformed, and validated data. It separates cleaning logic from raw ingestion and business aggregation.
- DLT Expectations are the modern, declarative way to enforce data quality rules in Databricks.
- You have granular control over how to handle bad data using three actions: warn, drop, or fail.
- Implementations are flexible, with clear syntax available in both SQL (
CONSTRAINT ... EXPECT) and Python (@dlt.expect...decorators). - For production-grade pipelines, monitoring the DLT event log is crucial for observability and alerting on data quality issues.
Preview of the Next Lesson:
We now have a high-quality, reliable dataset in our Silver layer. The next step is to make this data useful for specific business needs. In our upcoming lesson, we will focus on "Building an aggregated gold table for a specific business use case," where we'll transform our cleansed data into business-centric models ready for analytics and reporting.