| name | data-engineering-patterns-fabric-databricks |
| description | 600+ patterns and concepts for Azure Databricks, Microsoft Fabric, and PySpark data engineering - covering lakehouse architecture, Delta Lake, pipelines, and production best practices. |
| triggers | ["show me data engineering patterns for Fabric","how do I implement Delta Lake best practices","what are the Azure Databricks cluster optimization patterns","help me with PySpark transformation patterns","show me lakehouse architecture patterns","what are the Microsoft Fabric pipeline patterns","help with Unity Catalog governance patterns","show me production data engineering best practices"] |
Data Engineering Patterns - Fabric & Databricks
Skill by ara.so — Data Skills collection.
This skill provides access to 600+ field-tested data engineering patterns for Microsoft Fabric, Azure Databricks, and PySpark. These patterns cover everything from pipeline design and Delta Lake optimization to Unity Catalog governance and cost architecture.
What This Project Provides
A comprehensive collection of patterns organized into 12 books covering:
Microsoft Fabric (250 patterns):
- Pipelines and Data Factory
- Lakehouse and PySpark
- Warehouse and SQL
- Power BI in Fabric
- Architecture Patterns
Azure Databricks (350 patterns):
- Clusters and Compute
- Delta Lake
- Workflows and Orchestration
- Structured Streaming and Auto Loader
- Unity Catalog
- Databricks SQL and Photon
- Platform and Cost Architecture
PySpark:
- 88 concepts for production Spark across both platforms
Installation
Clone the repository to access all pattern PDFs:
git clone https://github.com/ssanjaychandra123/data-engineering-patterns.git
cd data-engineering-patterns
Repository Structure
data-engineering-patterns/
├── Fabric Patterns/
│ ├── Fabric Engineering Patterns Book I - Pipelines and Data Factory.pdf
│ ├── Fabric Engineering Patterns Book II - Lakehouse and PySpark.pdf
│ ├── Fabric Engineering Patterns Book III - Warehouse and SQL.pdf
│ ├── Fabric Engineering Patterns Book IV - Power BI in Fabric.pdf
│ └── Fabric Engineering Patterns Book V - Architecture Patterns.pdf
├── Databricks Patterns/
│ ├── Azure Databricks Engineering Patterns Book I - Clusters and Compute.pdf
│ ├── Azure Databricks Engineering Patterns Book II - Delta Lake.pdf
│ ├── Azure Databricks Engineering Patterns Book III - Workflows and Orchestration.pdf
│ ├── Azure Databricks Engineering Patterns Book IV - Structured Streaming and Auto Loader.pdf
│ ├── Azure Databricks Engineering Patterns Book V - Unity Catalog.pdf
│ ├── Azure Databricks Engineering Patterns Book VI - Databricks SQL and Photon.pdf
│ └── Azure Databricks Engineering Patterns Book VII - Platform and Cost Architecture.pdf
└── PySpark/
└── The PySpark Handbook for Fabric and Databricks.pdf
Key Pattern Categories
Microsoft Fabric Patterns
Pipeline and Data Factory Patterns
Common patterns include:
- Incremental data loading strategies
- Pipeline retry and error handling
- Parameter-driven pipeline design
- Activity dependencies and control flow
- Copy activity optimization
- Metadata-driven frameworks
Example incremental load pattern in Fabric Pipeline:
from datetime import datetime, timedelta
watermark = spark.conf.get("pipeline.watermark")
table_name = spark.conf.get("pipeline.tableName")
df = spark.read.format("delta") \
.load(f"abfss://source@storage.dfs.core.windows.net/{table_name}") \
.filter(f"modified_date > '{watermark}'")
df.write.format("delta") \
.mode("append") \
.option("mergeSchema", "true") \
.save(f"Tables/{table_name}")
new_watermark = df.agg({"modified_date": "max"}).collect()[0][0]
mssparkutils.notebook.exit(str(new_watermark))
Lakehouse and PySpark Patterns
Key patterns for Fabric Lakehouse:
from delta.tables import DeltaTable
updates_df = spark.read.format("parquet").load("Files/updates/")
target_table = DeltaTable.forPath(spark, "Tables/customers")
target_table.alias("target").merge(
updates_df.alias("updates"),
"target.customer_id = updates.customer_id"
).whenMatchedUpdate(set={
"name": "updates.name",
"email": "updates.email",
"updated_at": "updates.updated_at"
}).whenNotMatchedInsert(values={
"customer_id": "updates.customer_id",
"name": "updates.name",
"email": "updates.email",
"created_at": "updates.created_at",
"updated_at": "updates.updated_at"
}).execute()
Pattern: Optimize Delta tables in Fabric:
spark.sql(f"""
OPTIMIZE lakehouse.customers
ZORDER BY (customer_id, signup_date)
""")
spark.sql(f"""
VACUUM lakehouse.customers RETAIN 168 HOURS
""")
Warehouse and SQL Patterns
Pattern: Create warehouse tables with proper partitioning:
CREATE TABLE dw.fact_sales (
sale_id BIGINT,
customer_id BIGINT,
product_id BIGINT,
sale_amount DECIMAL(18,2),
sale_date DATE,
created_at TIMESTAMP
)
USING DELTA
PARTITIONED BY (sale_date);
INSERT INTO dw.fact_sales
SELECT
sale_id,
customer_id,
product_id,
sale_amount,
CAST(sale_date AS DATE) as sale_date,
created_at
FROM staging.sales
WHERE sale_date >= CURRENT_DATE - INTERVAL 7 DAYS;
Azure Databricks Patterns
Cluster and Compute Patterns
Pattern: Configure autoscaling cluster for cost optimization:
{
"cluster_name": "production-etl",
"spark_version": "13.3.x-scala2.12",
"node_type_id": "Standard_DS3_v2",
"autoscale": {
"min_workers": 2,
"max_workers": 8
},
"autotermination_minutes": 30,
"spark_conf": {
"spark.databricks.delta.preview.enabled": "true",
"spark.databricks.delta.properties.defaults.autoOptimize.optimizeWrite": "true",
"spark.databricks.delta.properties.defaults.autoOptimize.autoCompact": "true"
},
"aws_attributes": {
"availability": "SPOT_WITH_FALLBACK",
"spot_bid_price_percent": 100
}
}
Delta Lake Patterns
Pattern: Time travel and versioning:
df_version_10 = spark.read.format("delta") \
.option("versionAsOf", 10) \
.load("/mnt/delta/customers")
df_yesterday = spark.read.format("delta") \
.option("timestampAsOf", "2024-01-15 00:00:00") \
.load("/mnt/delta/customers")
history_df = spark.sql("DESCRIBE HISTORY delta.`/mnt/delta/customers`")
history_df.select("version", "timestamp", "operation", "operationMetrics").show()
Pattern: Change Data Feed (CDF) for incremental processing:
spark.sql("""
ALTER TABLE delta.customers
SET TBLPROPERTIES (delta.enableChangeDataFeed = true)
""")
changes_df = spark.read.format("delta") \
.option("readChangeFeed", "true") \
.option("startingVersion", 10) \
.option("endingVersion", 20) \
.table("delta.customers")
inserts = changes_df.filter("_change_type = 'insert'")
updates = changes_df.filter("_change_type = 'update_postimage'")
deletes = changes_df.filter("_change_type = 'delete'")
Structured Streaming Patterns
Pattern: Auto Loader with schema evolution:
checkpoint_path = "/mnt/checkpoints/raw_files"
target_path = "/mnt/delta/bronze/raw_data"
df = spark.readStream.format("cloudFiles") \
.option("cloudFiles.format", "json") \
.option("cloudFiles.schemaLocation", checkpoint_path + "/schema") \
.option("cloudFiles.inferColumnTypes", "true") \
.option("cloudFiles.schemaEvolutionMode", "addNewColumns") \
.load("/mnt/landing/raw_files/")
query = df.writeStream \
.format("delta") \
.option("checkpointLocation", checkpoint_path) \
.option("mergeSchema", "true") \
.trigger(availableNow=True) \
.start(target_path)
query.awaitTermination()
Pattern: Streaming aggregations with watermarking:
from pyspark.sql.functions import window, col
stream_df = spark.readStream.format("delta") \
.table("events")
aggregated = stream_df \
.withWatermark("event_time", "10 minutes") \
.groupBy(
window(col("event_time"), "5 minutes"),
col("user_id")
) \
.agg({
"event_id": "count",
"amount": "sum"
})
query = aggregated.writeStream \
.format("delta") \
.outputMode("append") \
.option("checkpointLocation", "/mnt/checkpoints/aggregations") \
.toTable("event_aggregations")
Unity Catalog Patterns
Pattern: Create governed table with row-level security:
spark.sql("""
CREATE SCHEMA IF NOT EXISTS main.finance
COMMENT 'Finance department data'
LOCATION 'abfss://data@storage.dfs.core.windows.net/finance'
""")
spark.sql("""
CREATE TABLE IF NOT EXISTS main.finance.transactions (
transaction_id BIGINT,
account_id BIGINT,
amount DECIMAL(18,2),
region STRING,
transaction_date DATE
)
USING DELTA
TBLPROPERTIES ('delta.enableChangeDataFeed' = 'true')
""")
spark.sql("""
CREATE FUNCTION main.finance.region_filter(region STRING)
RETURN IF(
IS_MEMBER('data_engineers'),
TRUE,
region = current_user()
)
""")
spark.sql("""
ALTER TABLE main.finance.transactions
SET ROW FILTER main.finance.region_filter ON (region)
""")
Pattern: Column masking with Unity Catalog:
spark.sql("""
CREATE FUNCTION main.finance.mask_ssn(ssn STRING)
RETURN CASE
WHEN IS_MEMBER('finance_managers') THEN ssn
ELSE CONCAT('XXX-XX-', RIGHT(ssn, 4))
END
""")
spark.sql("""
ALTER TABLE main.finance.customers
ALTER COLUMN ssn
SET MASK main.finance.mask_ssn
""")
Workflows and Orchestration Patterns
Pattern: Create parameterized Databricks job:
dbutils.widgets.text("date", "")
dbutils.widgets.text("environment", "prod")
processing_date = dbutils.widgets.get("date")
env = dbutils.widgets.get("environment")
df = spark.read.format("delta") \
.load(f"/mnt/{env}/data") \
.filter(f"date = '{processing_date}'")
result_df = df.groupBy("category").count()
result_df.write.format("delta").mode("overwrite") \
.save(f"/mnt/{env}/results/{processing_date}")
dbutils.notebook.exit(f"Processed {result_df.count()} records")
Pattern: Job definition with retry logic:
{
"name": "daily-etl-pipeline",
"tasks": [
{
"task_key": "extract",
"notebook_task": {
"notebook_path": "/Workflows/extract",
"base_parameters": {
"date": "{{job.start_time.date}}",
"environment": "prod"
}
},
"existing_cluster_id": "{{cluster_id}}",
"max_retries": 2,
"timeout_seconds": 3600
},
{
"task_key": "transform",
"depends_on": [{"task_key"
PySpark Production Patterns
Broadcast Join Pattern
from pyspark.sql.functions import broadcast
dim_products = spark.table("dim.products")
fact_sales = spark.table("fact.sales")
result = fact_sales.join(
broadcast(dim_products),
fact_sales.product_id == dim_products.product_id,
"left"
)
Partitioning and Bucketing Pattern
df.write.format("delta") \
.mode("overwrite") \
.partitionBy("year", "month") \
.option("maxRecordsPerFile", 1000000) \
.save("/mnt/delta/partitioned_data")
df.write.format("delta") \
.mode("overwrite") \
.bucketBy(100, "customer_id") \
.sortBy("transaction_date") \
.saveAsTable("bucketed_transactions")
Error Handling Pattern
from pyspark.sql.functions import col, when, lit
from pyspark.sql.utils import AnalysisException
try:
df = spark.read.format("delta") \
.option("enforceSchema", "true") \
.load("/mnt/delta/source")
valid_df = df.filter(col("amount") > 0) \
.filter(col("customer_id").isNotNull())
invalid_df = df.filter(
(col("amount") <= 0) |
(col("customer_id").isNull())
).withColumn("error_reason",
when(col("amount") <= 0, lit("Invalid amount"))
.when(col("customer_id").isNull(), lit("Missing customer_id"))
)
valid_df.write.format("delta").mode("append") \
.save("/mnt/delta/target")
if invalid_df.count() > 0:
invalid_df.write.format("delta").mode("append") \
.save("/mnt/delta/quarantine")
except AnalysisException as e:
print(f"Schema mismatch: {str(e)}")
df = spark.read.() \
.option(, ) \
.load()
Performance Optimization Pattern
from pyspark.sql.functions import col, current_timestamp
df_cached = spark.table("dimension.products") \
.filter(col("is_active") == True) \
.cache()
from pyspark.storagelevel import StorageLevel
df_persisted = large_df.repartition(200, "partition_key") \
.persist(StorageLevel.MEMORY_AND_DISK)
spark.conf.set("spark.sql.adaptive.enabled", "true")
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")
spark.conf.set("spark.sql.adaptive.skewJoin.enabled", "true")
spark.conf.set("spark.sql.optimizer.dynamicPartitionPruning.enabled", "true")
Common Use Cases
Medallion Architecture Pattern
bronze_df = spark.read.format("cloudFiles") \
.option("cloudFiles.format", "json") \
.load("/mnt/landing/") \
.withColumn("ingestion_time", current_timestamp())
bronze_df.write.format("delta") \
.mode("append") \
.save("/mnt/delta/bronze/raw_events")
from pyspark.sql.functions import col, to_timestamp
silver_df = spark.read.format("delta") \
.load("/mnt/delta/bronze/raw_events") \
.filter(col("event_type").isNotNull()) \
.withColumn("event_timestamp", to_timestamp("timestamp")) \
.dropDuplicates(["event_id"]) \
.select("event_id", "event_type", "user_id", "event_timestamp", "properties")
silver_df.write.format("delta") \
.mode("append") \
.option("mergeSchema", "true") \
.save("/mnt/delta/silver/events")
gold_df = spark.read.format("delta") \
.load("/mnt/delta/silver/events") \
.groupBy("user_id", "event_type") \
.agg({
"event_id": "count",
"event_timestamp": "max"
})
gold_df.write.format() \
.mode() \
.save()
SCD Type 2 Pattern
from delta.tables import DeltaTable
from pyspark.sql.functions import col, current_timestamp, lit
source_df = spark.read.format("parquet").load("/mnt/staging/customers")
target_table = DeltaTable.forPath(spark, "/mnt/delta/dim_customers")
changes = source_df.alias("source") \
.join(
target_table.toDF().filter("is_current = true").alias("target"),
"customer_id",
"left"
) \
.filter(
col("target.customer_id").isNull() |
(col("source.name") != col("target.name")) |
(col("source.email") != col("target.email"))
)
target_table.alias("target").merge(
changes.alias("changes"),
"target.customer_id = changes.customer_id AND target.is_current = true"
).whenMatchedUpdate(set={
"is_current": lit(False),
"end_date": current_timestamp()
}).execute()
new_records = changes.select(
col("customer_id"),
col("name"),
col("email"),
current_timestamp().alias("start_date"),
lit(None).alias("end_date"),
lit(True).alias("is_current")
)
new_records.write.().mode() \
.save()
Configuration Best Practices
Fabric Configuration
spark.conf.set("spark.sql.adaptive.enabled", "true")
spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true")
spark.conf.set("spark.databricks.delta.optimizeWrite.enabled", "true")
spark.conf.set("spark.databricks.delta.autoCompact.enabled", "true")
from notebookutils import mssparkutils
storage_key = mssparkutils.credentials.getSecret(
"https://keyvault.vault.azure.net/",
"storage-account-key"
)
workspace_id = mssparkutils.env.getWorkspaceId()
Databricks Configuration
storage_account_key = dbutils.secrets.get(
scope="azure-key-vault",
key="storage-account-key"
)
dbutils.fs.mount(
source=f"abfss://data@{storage_account}.dfs.core.windows.net/",
mount_point="/mnt/data",
extra_configs={
"fs.azure.account.auth.type": "OAuth",
"fs.azure.account.oauth.provider.type":
"org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider",
"fs.azure.account.oauth2.client.id": dbutils.secrets.get("azure-sp", "client-id"),
"fs.azure.account.oauth2.client.secret": storage_account_key,
"fs.azure.account.oauth2.client.endpoint":
f"https://login.microsoftonline.com/{tenant_id}/oauth2/token"
}
)
spark.conf.set("spark.sql.shuffle.partitions", "200")
spark.conf.set("spark.sql.files.maxPartitionBytes", "134217728")
spark.conf.set("spark.sql.adaptive.skewJoin.skewedPartitionFactor", "5")
Troubleshooting
Performance Issues
Problem: Slow joins causing job timeouts
df.rdd.getNumPartitions()
df.groupBy("partition_key").count().orderBy(col("count").desc()).show()
from pyspark.sql.functions import rand, concat
df_balanced = df.withColumn("salt", (rand() * 10).cast("int")) \
.withColumn("salted_key", concat(col("partition_key"), lit("_"), col("salt"))) \
.repartition(200, "salted_key")
Problem: Small file problem in Delta tables
spark.sql("DESCRIBE DETAIL delta.`/mnt/delta/table`").select("numFiles", "sizeInBytes").show()
spark.sql("OPTIMIZE delta.`/mnt/delta/table`")
spark.sql("OPTIMIZE delta.`/mnt/delta/table` WHERE date >= '2024-01-01'")
Schema Evolution Issues
Problem: Schema mismatch errors when appending data
df.write.format("delta") \
.mode("append") \
.option("mergeSchema", "true") \
.save("/mnt/delta/table")
df.write.format("delta") \
.mode("overwrite") \
.option("overwriteSchema", "true") \
.save("/mnt/delta/table")
spark.read.format("delta").load("/mnt/delta/table").printSchema()
Memory Issues
Problem: Out of memory errors during processing
df_repartitioned = df.repartition(400)
from pyspark.sql.window import Window
window_spec = Window.partitionBy("category").orderBy("date")
df_windowed = df.withColumn("row_num", row_number().over(window_spec))
spark.conf.set("spark.memory.fraction", "0.6")
spark.conf.set("spark.memory.storageFraction", "0.3")
Streaming Issues
Problem: Checkpoint directory conflicts
checkpoint_base = "/mnt/checkpoints"
stream_id = "user_events_stream"
query = df.writeStream \
.format("delta") \
.option("checkpointLocation", f"{checkpoint_base}/{stream_id}") \
.start("/mnt/delta/target")
Problem: Watermark not advancing
from pyspark.sql.functions import to_timestamp
df_with_timestamp = df.withColumn(
"event_time",
to_timestamp(col("timestamp_string"), "yyyy-MM-dd HH:mm:ss")
)
stream_df = df_with_timestamp.withWatermark("event_time", "30 minutes")
Cost Optimization Patterns
Databricks Cost Optimization
cluster_config = {
"instance_pool_id": "pool-abc123",
"autotermination_minutes": 15,
"autoscale": {
"min_workers": 1,
"max_workers": 10
}
}
aws_attributes = {
"availability": "SPOT_WITH_FALLBACK",
"zone_id": "us-west-2a",
"spot_bid_price_percent": 100
}
spark.sql("""
OPTIMIZE prod.sales_transactions
ZORDER BY (customer_id, transaction_date)
""")
spark.sql("VACUUM prod.sales_transactions RETAIN 168 HOURS")
Fabric Cost Optimization
df.write.format("delta") \
.option("compression", "zstd") \
.mode("overwrite") \
.save("Tables/compressed_data")
Resources
Author
Sanjay Chandra - Enterprise data platform architect and advisor
These patterns are compiled from real production implementations across Microsoft Fabric and Azure Databricks platforms. The material is continuously updated as platforms evolve.