Business Professionals
Power BI | Power Pivot | Power Query | DAX
Cloud Flows | RPA | AI Builder | Copilot
60+ Formulas | Data Stories | Advanced Reporting & Modeling
VB Programming | Report Automation |
MS-Office Automation
Techno-Business Professionals
Power BI | Power Query | Advanced DAX | SQL - Query &
Programming
Microsoft Fabric | Power BI | Power Query | Advanced DAX |
SQL - Query & Programming
Power BI | Power Apps | Power Automate | Copilot Studio | Power Pages | Dataverse
Microsoft Power Apps | Microsoft Power Automate
Power BI | Adv. DAX | SQL (Query & Programming) |
VBA | Python | Web Scrapping | API Integration
Power BI | Power Apps | Power Automate |
SQL (Query & Programming)
Power BI | Adv. DAX | Power Apps | Power Automate |
SQL (Query & Programming) | VBA | Python | Web Scrapping | API Integration
Power Apps | Power Automate | SQL | VBA | Python |
Web Scraping | RPA | API Integration
Technology Professionals
Power BI | DAX | SQL | ETL with SSIS | SSAS | VBA | Python
Power BI | SQL | Azure Data Lake | Synapse Analytics |
Data Factory | Databricks | Power Apps | Power Automate |
Azure Analysis Services
Microsoft Fabric | Power BI | SQL | Lakehouse |
Data Factory (Pipelines) | Dataflows Gen2 | KQL | Delta Tables | Power Apps | Power Automate
Power BI | Power Apps | Power Automate | SQL | VBA | Python | API Integration
Power BI | Advanced DAX | Databricks | SQL | Lakehouse Architecture
Business Professionals
Power BI | Power Pivot | Power Query | DAX
Cloud Flows | RPA | AI Builder | Copilot
60+ Formulas | Data Stories | Advanced Reporting & Modeling
VB Programming | Report Automation |
MS-Office Automation
Techno-Business Professionals
Power BI | Power Query | Advanced DAX | SQL - Query &
Programming
Microsoft Fabric | Power BI | Power Query | Advanced DAX |
SQL - Query & Programming
Power BI | Power Apps | Power Automate | Copilot Studio | Power Pages | Dataverse
Microsoft Power Apps | Microsoft Power Automate
Power BI | Adv. DAX | SQL (Query & Programming) |
VBA | Web Scrapping | API Integration
Power BI | Power Apps | Power Automate |
SQL (Query & Programming)
Power BI | Adv. DAX | Power Apps | Power Automate |
SQL (Query & Programming) | VBA | Web Scrapping | API Integration
Power Apps | Power Automate | SQL | VBA |
Web Scraping | RPA | API Integration
Technology Professionals
Power BI | DAX | SQL | ETL with SSIS | SSAS | VBA
Power BI | SQL | Azure Data Lake | Synapse Analytics |
Data Factory | Azure Analysis Services
Microsoft Fabric | Power BI | SQL | Lakehouse |
Data Factory (Pipelines) | Dataflows Gen2 | KQL | Delta Tables
Power BI | Power Apps | Power Automate | SQL | VBA | API Integration
Power BI | Advanced DAX | Databricks | SQL | Lakehouse Architecture
LEARN THIS HANDS ON
Microsoft Fabric & Power BI
You want a Microsoft Fabric Lakehouse that feeds reliable BI without turning into a swamp. This article walks through concrete design patterns for Bronze, Silver, and Gold layers in Fabric, with naming, folder structure, transformation patterns, and example code you can adapt directly. If you want to go deeper into end‑to‑end patterns, pair this with structured practice in a course on modern Fabric data engineering.
Before you start creating Lakehouses and Pipelines, lock in three decisions:
Single source of truth per domain
Sales, Finance, Operations) is usually enough.Layered model is non‑negotiable
Schema and naming discipline
sales_order_header, order_date, customer_key.A simple, repeatable pattern for one domain:
wh-sales-analyticslh-sales/Files/bronze/<source_system>/<entity> (optional if you stage files first)/Tables/bronze_<entity>/Tables/silver_<entity>/Tables/gold_<mart_name>_<table>Example for Sales:
bronze_orders_rawsilver_orders_header, silver_orders_linegold_sales_fct_sales, gold_sales_dim_customer, gold_sales_dim_dateThis keeps three things obvious at a glance:
Bronze is about ingesting and preserving source data with minimal logic.
_load_date, _source_file, _batch_id).Immutable
Append‑only pattern
ingestion_date).One table per source object
bronze_erp_sales_order_headerbronze_erp_sales_order_linebronze_crm_accountA typical pattern when landing from SQL Server into bronze_orders_raw:
let
Source = Sql.Database("sql-prod", "ERP"),
Orders = Source{[Schema="dbo",Item="SalesOrders"]}[Data],
KeepColumns = Table.SelectColumns(Orders,
{"OrderID", "CustomerID", "OrderDate", "Status", "TotalAmount"}),
AddLoadDate = Table.AddColumn(KeepColumns, "_load_date", each DateTimeZone.FixedUtcNow(), type datetimezone),
AddSource = Table.AddColumn(AddLoadDate, "_source_system", each "ERP", type text)
in
AddSource
Sink this into the Lakehouse as bronze_erp_sales_order_header (Delta table). The only logic is metadata and column selection.
Silver is where you fix data and align semantics across sources.
customer_business_key).Use Fabric Notebooks (PySpark) or Dataflows Gen2 for these transformations.
You often keep both:
customer_number (from ERP).customer_key (generated in Silver or Gold).If you want to generate keys in Silver using PySpark:
from pyspark.sql import functions as F
from pyspark.sql.window import Window
bronze_customers = spark.read.table("lh_sales.bronze_erp_customer")
# Basic cleaning
clean_customers = (
bronze_customers
.dropDuplicates(["CustomerNumber"])
.withColumn("CustomerName", F.initcap("CustomerName"))
.withColumn("IsActive", (F.col("Status") == F.lit("Active")).cast("boolean"))
)
# Generate stable surrogate key
w = Window.orderBy("CustomerNumber")
silver_customers = clean_customers.withColumn("customer_key", F.row_number().over(w))
silver_customers.write.format("delta").mode("overwrite").saveAsTable("lh_sales.silver_customer")
If you have customers in ERP and CRM:
bronze_erp_customer, bronze_crm_account.silver_customer that merges both.Pattern:
_source_system, _source_id).Gold is what your BI tools connect to. It should be predictable, simple, and optimised for analytics.
fct_sales, fct_invoice, fct_inventory.dim_customer, dim_product, dim_date.From Silver orders header and line to gold_sales_fct_sales:
from pyspark.sql import functions as F
orders_header = spark.read.table("lh_sales.silver_orders_header")
orders_line = spark.read.table("lh_sales.silver_orders_line")
customer_dim = spark.read.table("lh_sales.gold_sales_dim_customer")
product_dim = spark.read.table("lh_sales.gold_sales_dim_product")
# Join header and line
sales = (
orders_line.alias("l")
.join(orders_header.alias("h"), "OrderID", "inner")
.join(customer_dim.alias("c"), "CustomerBusinessKey", "left")
.join(product_dim.alias("p"), "ProductCode", "left")
.select(
F.col("l.OrderLineID").alias("sales_key"),
F.col("h.OrderDate").alias("order_date"),
F.col("c.customer_key"),
F.col("p.product_key"),
F.col("l.Quantity"),
F.col("l.NetAmount").alias("net_amount"),
F.col("h.CurrencyCode").alias("currency_code")
)
)
sales.write.format("delta").mode("overwrite").saveAsTable("lh_sales.gold_sales_fct_sales")
gold_<subject>_dim_<name>
gold_sales_dim_customergold_sales_dim_productgold_<subject>_fct_<name>
gold_sales_fct_salesgold_sales_fct_returnsThis keeps multiple subject areas manageable inside one Lakehouse.
In Microsoft Fabric, you can create a semantic model directly on top of Lakehouse tables.
For clean governance:
Limit model sources to Gold tables
Hide technical columns
*_key) and metadata columns (_load_date) from report authors.Create measures, not calculated columns, where possible
Example DAX measures on gold_sales_fct_sales:
Total Sales :=
SUM ( 'gold_sales_fct_sales'[net_amount] )
Total Quantity :=
SUM ( 'gold_sales_fct_sales'[Quantity] )
Sales LY :=
CALCULATE (
[Total Sales],
DATEADD ( 'gold_sales_dim_date'[Date], -1, YEAR )
)
Customer Count :=
DISTINCTCOUNT ( 'gold_sales_dim_customer'[customer_key] )
These measures live in the semantic model; the Lakehouse remains focused on data, not business calculations.
You have three main options in Fabric:
Data Pipelines (copy + notebooks)
Dataflows Gen2
Notebooks (PySpark)
A simple daily pattern:
For updating a Silver table from Bronze incrementally:
MERGE INTO lh_sales.silver_orders_header AS tgt
USING (
SELECT *
FROM lh_sales.bronze_erp_sales_order_header
WHERE _load_date >= DATEADD(day, -1, CURRENT_TIMESTAMP)
) AS src
ON tgt.OrderID = src.OrderID
WHEN MATCHED THEN
UPDATE SET
tgt.OrderDate = src.OrderDate,
tgt.Status = src.Status,
tgt.TotalAmount = src.TotalAmount
WHEN NOT MATCHED THEN
INSERT (OrderID, OrderDate, Status, TotalAmount)
VALUES (src.OrderID, src.OrderDate, src.Status, src.TotalAmount);
Same idea applies Silver → Gold for facts and dimensions.
Common failure mode: every team gets its own Gold tables, and definitions diverge.
A more sustainable pattern:
Shared conformed layer
gold_*_dim_* tables per domain.Thin report‑specific models
Data contracts for Gold
Before you build anything, sketch your Bronze/Silver/Gold pattern for a single domain on one page: source objects → Bronze tables → Silver entities → Gold facts/dimensions → Power BI model. If you can’t draw that flow clearly, fix the design on paper first; it’s far cheaper than refactoring a messy Lakehouse later.
Microsoft Fabric
New
Next Batches Now Live
Power BI
SQL
Power Apps
Power Automate
Microsoft Fabrics
Azure Data Engineering