Skip to main content

databricks-data-engineering

Production data engineering pipelines following medallion architecture (Bronze/Silver/Gold layers) with data ingestion, transformation, quality checks, Delta Lake optimization, and orchestration. Use when building ETL pipelines, medallion architecture, data lakes, or data transformation workflows.

Source facts

Repository
databricks-solutions/databricks-exec-code-mcp
Last source activity
January 19, 2026 at 14:10
Detected SKILL.md language
English
Stars
14
Forks
7

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
databricks-data-engineering
description
Production data engineering pipelines following medallion architecture (Bronze/Silver/Gold layers) with data ingestion, transformation, quality checks, Delta Lake optimization, and orchestration. Use when building ETL pipelines, medallion architecture, data lakes, or data transformation workflows.
allowed-tools
["Bash","Read","Write","Edit","Grep","Glob"]
model
claude-sonnet-4-5-20250929
user-invocable
true
# Databricks Data Engineering Pipelines Build production-grade data pipelines following medallion architecture (Bronze/Silver/Gold) with data quality checks, Delta Lake optimization, and multi-layer transformations. ## When to Use This Skill - Building ETL/ELT data pipelines - Implementing medallion architecture - Data lake transformations - Data quality and validation workflows - Incremental data processing - Batch data pipelines - Real-time streaming (structured streaming) ## Medallion Architecture The medallion architecture organizes data into three layers of increasing quality: ``` Bronze Layer (Raw/Landing) ↓ Silver Layer (Cleaned/Validated) ↓ Gold Layer (Business/Aggregated) ``` ### Bronze Layer (Raw Ingestion) - **Purpose**: Ingest raw data with minimal transformation - **Pattern**: Append-only, preserve source format - **Transformations**: Type casting, timestamp addition - **Storage**: Delta Lake tables - **Schema**: Flexible, can evolve ### Silver Layer (Cleaned Data) - **Purpose**: Cleaned, validated, and conformed data - **Pattern**: Deduplication, quality checks, schema enforcement - **Transformations**: Data quality rules, null handling, type validation - **Storage**: Delta Lake tables (optimized) - **Schema**: Strict, well-defined ### Gold Layer (Business-Ready) - **Purpose**: Aggregated, business-ready datasets - **Pattern**: Joins, aggregations, business logic - **Transformations**: Metrics, KPIs, analytics-ready views - **Storage**: Delta Lake tables (highly optimized) - **Schema**: Denormalized for analytics ## Complete Data Pipeline Workflow ### Phase 1: Schema Setup Use `databricks-unity-catalog` skill to create medallion schemas: ```python catalog = "de_prod" # Bronze - raw data create_schema( catalog_name=catalog, schema_name="bronze", comment="Raw ingested data. Minimal transformation. Append-only. 90-day retention." ) # Silver - cleaned data create_schema( catalog_name=catalog, schema_name="silver", comment="Cleaned and validated data. Deduplicated, quality-checked. 1-year retention." ) # Gold - business aggregates create_schema( catalog_name=catalog, schema_name="gold", comment="Business-ready aggregates. Optimized for analytics. 3-year retention." ) ``` ### Phase 2: Bronze Layer Development Use `databricks-testing` skill to test ingestion logic: ```python databricks_command( cluster_id="0123-456789-abc123", language="python", code=""" from pyspark.sql import functions as F # Ingest raw data raw_df = ( spark.read .format("json") # or csv, parquet, etc. .option("inferSchema", "true") .load("/mnt/source/events/*.json") ) # Add ingestion metadata bronze_df = ( raw_df .withColumn("ingestion_timestamp", F.current_timestamp()) .withColumn("ingestion_date", F.current_date()) .withColumn("source_file", F.input_file_name()) ) print(f"Ingested {bronze_df.count()} records") # Save to bronze bronze_df.write \\ .format("delta") \\ .mode("append") \\ .saveAsTable("de_prod.bronze.raw_events") print("Bronze ingestion complete") """ ) ``` ### Phase 3: Silver Layer Development Use `databricks-testing` skill to test cleaning logic: **Complete Silver Layer Notebook:** ```python # Databricks notebook source # MAGIC %md # MAGIC # Silver Layer - Data Cleaning & Validation # MAGIC # MAGIC Transforms bronze data into cleaned, validated silver tables # COMMAND ---------- # Widget parameterization try: catalog = dbutils.widgets.get("catalog") except: catalog = "de_dev" try: bronze_schema = dbutils.widgets.get("bronze_schema") except: bronze_schema = "bronze" try: silver_schema = dbutils.widgets.get("silver_schema") except: silver_schema = "silver" try: batch_date = dbutils.widgets.get("batch_date") except: from datetime import date batch_date = str(date.today()) print(f"Processing silver layer:") print(f" Catalog: {catalog}") print(f" Bronze schema: {bronze_schema}") print(f" Silver schema: {silver_schema}") print(f" Batch date: {batch_date}") # COMMAND ---------- from pyspark.sql import functions as F from pyspark.sql.window import Window # Read from bronze (incremental) bronze_df = spark.read.table(f"{catalog}.{bronze_schema}.raw_events") \\ .filter(F.col("ingestion_date") == batch_date) print(f"Bronze records for {batch_date}: {bronze_df.count()}") # COMMAND ---------- # Data quality checks BEFORE cleaning print("Data Quality Report - Before Cleaning:") print(f" Total records: {bronze_df.count()}") print(f" Null event_id: {bronze_df.filter(F.col('event_id').isNull()).count()}") print(f" Null timestamp: {bronze_df.filter(F.col('timestamp').isNull()).count()}") print(f" Duplicate event_id: {bronze_df.groupBy('event_id').count().filter(F.col('count') > 1).count()}") # Record initial count for tracking initial_count = bronze_df.count() # COMMAND ---------- # Cleaning transformations silver_df = ( bronze_df # Remove records with null in critical fields .filter(F.col("event_id").isNotNull()) .filter(F.col("timestamp").isNotNull()) .filter(F.col("user_id").isNotNull()) # Deduplicate - keep latest by timestamp .withColumn("row_num", F.row_number().over( Window.partitionBy("event_id").orderBy(F.col("timestamp").desc()) )) .filter(F.col("row_num") == 1) .drop("row_num") # Type casting and validation .withColumn("amount", F.col("amount").cast("double")) .withColumn("quantity", F.col("quantity").cast("int")) .withColumn("timestamp", F.col("timestamp").cast("timestamp")) # Remove invalid values .filter(F.col("amount") >= 0) # No negative amounts .filter(F.col("quantity") > 0) # Quantity must be positive # Add silver layer metadata .withColumn("silver_processed_at", F.current_timestamp()) .withColumn("silver_processing_date", F.current_date()) # Drop ingestion metadata (not needed in silver) .drop("source_file", "ingestion_timestamp", "ingestion_date") ) # COMMAND ---------- # Data quality checks AFTER cleaning final_count = silver_df.count() removed_count = initial_count - final_count print(f"\\nData Quality Report - After Cleaning:") print(f" Clean records: {final_count}") print(f" Removed records: {removed_count} ({removed_count/initial_count*100:.2f}%)") # Validation assertions assert silver_df.filter(F.col("event_id").isNull()).count() == 0, "Null event_ids remain" assert silver_df.filter(F.col("timestamp").isNull()).count() == 0, "Null timestamps remain" assert silver_df.groupBy("event_id").count().filter(F.col("count") > 1).count() == 0, "Duplicates remain" print("✓ All quality checks passed") # COMMAND ---------- # Write to silver (merge for idempotency) from delta.tables import DeltaTable silver_table = f"{catalog}.{silver_schema}.clean_events" # Check if table exists if spark.catalog.tableExists(silver_table): # Merge into existing table (upsert pattern) deltaTable = DeltaTable.forName(spark, silver_table) deltaTable.alias("target").merge( silver_df.alias("source"), "target.event_id = source.event_id" ).whenMatchedUpdateAll() \\ .whenNotMatchedInsertAll() \\ .execute() print(f"Merged {final_count} records into {silver_table}") else: # Create table silver_df.write \\ .format("delta") \\ .mode("overwrite") \\ .saveAsTable(silver_table) print(f"Created {silver_table} with {final_count} records") # COMMAND ---------- # Optimize Delta table spark.sql(f"OPTIMIZE {silver_table}") print(f"✓ Optimized {silver_table}") # Update statistics spark.sql(f"ANALYZE TABLE {silver_table} COMPUTE STATISTICS") print(f"✓ Updated statistics for {silver_table}") # COMMAND ---------- # Z-order for query optimization (optional) spark.sql(f"OPTIMIZE {silver_table} ZORDER BY (event_id, timestamp)") print(f"✓ Z-ordered {silver_table}") # COMMAND ---------- print(f"\\n{'='*50}") print("Silver layer processing complete!") print(f" Input (Bronze): {initial_count} records") print(f" Output (Silver): {final_count} records") print(f" Quality: {final_count/initial_count*100:.2f}% retention") print(f"{'='*50}") ``` ### Phase 4: Gold Layer Development Use `databricks-testing` skill to test aggregation logic: **Complete Gold Layer Notebook:** ```python # Databricks notebook source # MAGIC %md # MAGIC # Gold Layer - Business Aggregates # MAGIC # MAGIC Creates business-ready aggregated datasets for analytics # COMMAND ---------- # Widget parameterization try: catalog = dbutils.widgets.get("catalog") except: catalog = "de_dev" try: silver_schema = dbutils.widgets.get("silver_schema") except: silver_schema = "silver" try: gold_schema = dbutils.widgets.get("gold_schema") except: gold_schema = "gold" print(f"Processing gold layer:") print(f" Catalog: {catalog}") print(f" Silver schema: {silver_schema}") print(f" Gold schema: {gold_schema}") # COMMAND ---------- from pyspark.sql import functions as F from pyspark.sql.window import Window # Read from silver silver_df = spark.table(f"{catalog}.{silver_schema}.clean_events") print(f"Silver records: {silver_df.count()}") # COMMAND ---------- # Daily aggregations by user daily_user_metrics = ( silver_df .withColumn("event_date", F.to_date("timestamp")) .groupBy("event_date", "user_id") .agg( F.count("*").alias("event_count"), F.sum("amount").alias("total_amount"), F.avg("amount").alias("avg_amount"), F.sum("quantity").alias("total_quantity"), F.countDistinct("event_id").alias("unique_events"), F.min("timestamp").alias("first_event_time"), F.max("timestamp").alias("last_event_time") ) .withColumn("gold_created_at", F.current_timestamp()) ) print(f"Daily user metrics: {daily_user_metrics.count()} records") # COMMAND ----------
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub