Learn how to create OneLake shortcuts in a Fabric Warehouse that point to lakehouse Delta tables — enabling T-SQL queries across both engines with zero data duplication. This lesson covers the full pattern from shortcut creation to cross-engine joins, security configuration, metadata sync, and performance tuning.

Here's a scenario you'll encounter sooner or later: your team has invested real effort in building a medallion lakehouse architecture. The gold layer Delta tables are clean, well-structured, and already powering Direct Lake reports in Power BI. Then a business analyst asks, "Can I just query this in SQL Server Management Studio with proper T-SQL joins?" Or a data engineer needs to build a stored procedure that cross-references gold layer transaction data with warehouse-specific dimension tables. Suddenly you need a Fabric Warehouse — but the last thing you want to do is copy all that lakehouse data into a second storage location, pay twice for the compute to keep it fresh, and introduce sync lag between two versions of the same truth.
This is exactly the problem that OneLake shortcuts solve elegantly. By creating a shortcut inside a Fabric Warehouse that points to Delta tables in your lakehouse, the warehouse can execute T-SQL against the underlying Parquet files in OneLake without moving a single byte. The lakehouse remains the system of record; the warehouse gains full T-SQL query capability over that data. You get both engines working over one physical copy of the data.
By the end of this lesson, you'll know how to configure this pattern end-to-end, understand why it works at the storage layer, write cross-engine T-SQL queries that join warehouse-native tables to lakehouse-sourced shortcuts, and avoid the common traps that cause permissions failures, stale metadata, and query performance surprises.
What you'll learn:
You should be comfortable with the following before diving in:
Before you touch any configuration, you need to understand why this is possible at all — because it's not obvious if you're coming from a traditional data platform background where separate systems mean separate storage.
In Microsoft Fabric, both lakehouses and warehouses store their underlying data in OneLake, Fabric's unified storage layer. A lakehouse stores its Delta tables as Parquet files plus _delta_log transaction logs under a path like {workspace}/lakehouses/{lakehouse-name}/Tables/{table-name}/. A Fabric Warehouse stores its tables similarly in OneLake under {workspace}/warehouses/{warehouse-name}/. Both are just files in the same OneLake file system.
A shortcut is a metadata pointer — a symbolic link inside OneLake — that says "when something accesses this path, redirect to that path." When a warehouse shortcut points to a lakehouse table's OneLake path, the warehouse's T-SQL engine reads the Parquet files directly from the lakehouse location. No ETL. No COPY INTO. No data movement. The warehouse compute layer reads the data through the shortcut pointer as though it lives natively in the warehouse.
Key insight
Shortcuts don't replicate data — they redirect read I/O. The physical Parquet files exist exactly once in OneLake. The lakehouse writes to them, and the warehouse reads from them through the shortcut pointer. This means updates written by Spark or Dataflow Gen2 to the lakehouse table are immediately visible in the warehouse without any refresh step.
This is meaningfully different from creating a linked server or an external table that queries a remote database. There's no network hop to another service. The warehouse engine and the lakehouse engine are both reading the same OneLake storage — it's more like two query engines sharing the same disk than two systems talking over a network.
Let's ground this in a real-world scenario. You're the data engineer for a mid-size retail company. Your setup looks like this:
Lakehouse: retail_gold — contains gold layer Delta tables produced by PySpark transformations, including:
fact_sales — 200M+ row transaction fact table, partitioned by sale_datedim_customer — 1.2M customer records with demographic attributesdim_product — 85,000 product records with hierarchy and cost attributesWarehouse: retail_warehouse — contains tables managed directly by the warehouse engine, including:
finance.budget_targets — quarterly budget targets by product category and region, loaded by a finance team pipelineops.territory_mapping — sales territory assignments maintained by operations, updated via T-SQL proceduresThe reporting team needs queries that join fact_sales from the lakehouse against budget_targets from the warehouse — comparing actuals to targets. The finance analysts also want to run ad-hoc T-SQL queries, not Spark notebooks. Rather than copying the entire fact table and dimension tables into the warehouse, you'll create shortcuts so the warehouse can read them directly.
Note
This scenario assumes your lakehouse and warehouse are in the same Fabric workspace. Cross-workspace shortcuts are also supported, but require additional attention to workspace-level permissions which we'll cover in the security section.
Shortcuts in a warehouse can only point to Delta table paths — not to raw files in the Files section of a lakehouse. If your lakehouse tables appear in the Tables section and were created as managed Delta tables (via Spark, Dataflow Gen2, or pipeline Copy Activity with Delta as the target format), you're good.
Open your retail_gold lakehouse in the Fabric portal and switch to the SQL analytics endpoint view. Run a quick validation query:
SELECT
COUNT(*) AS row_count,
MAX(sale_date) AS latest_sale,
MIN(sale_date) AS earliest_sale
FROM dbo.fact_sales;
If this returns results, the Delta table is valid and readable through the SQL engine. That's a prerequisite for the warehouse shortcut to work — if the lakehouse's own SQL endpoint can't read the table, neither can the warehouse via shortcut.
Also note the exact table names. They'll become the shortcut names inside the warehouse, and the warehouse T-SQL engine is case-sensitive in how it resolves them.
Tip
Run DESCRIBE DETAIL on your Delta tables in a Spark notebook to verify the table format version and file statistics. Tables written by older Spark versions using Delta protocol 1.x work fine, but if you have tables written with Delta 3.x liquid clustering features, verify that the Fabric warehouse runtime supports that Delta reader protocol version before assuming the shortcut will work transparently.
In the Fabric portal, navigate to your retail_warehouse item and open it. You'll land in the warehouse editor, which shows the object explorer on the left with your warehouse's native schemas and tables.
To create a shortcut, you need to reach the warehouse's OneLake view, not the SQL editor. Look for the New shortcut option — in the current Fabric UI, you access this through the toolbar at the top of the warehouse editor. Click the New shortcut button (it's typically in the same toolbar area where you'd see options for new tables or queries).
This opens the New shortcut wizard, which will ask you to choose the shortcut source. You'll see options including:
Choose Microsoft OneLake. This is the key distinction — you're not pointing to an external storage account, you're creating an internal OneLake-to-OneLake shortcut. Authentication is handled automatically via the Fabric identity model, which means no credentials to manage and no expiry surprises.
Warning
Do not choose ADLS Gen2 even if your lakehouse data is technically stored in an Azure storage account behind OneLake. Always use the OneLake option for Fabric-to-Fabric shortcuts. Using the ADLS Gen2 path directly bypasses Fabric's access control model and creates a credential management burden you don't need.
After selecting Microsoft OneLake as the source, the wizard presents a tree view of your OneLake namespace. You'll navigate:
retail_goldretail_gold lakehousefact_salesThe wizard will show you the OneLake path it will use, which looks something like:
onelake://retail_gold.lakehouse/Tables/fact_sales
Give the shortcut a name. By default it'll match the table name (fact_sales), which is what you want — keeping names consistent makes T-SQL queries predictable and avoids confusion when colleagues look at the warehouse object catalog.
Click Create. Repeat this process for dim_customer and dim_product.
After creating all three shortcuts, refresh the object explorer in the warehouse editor. You'll see the shortcut tables appear in the warehouse's object tree, typically under the dbo schema, distinguished from native warehouse tables by a small shortcut icon.
Note
Shortcuts in a warehouse are exposed as external tables from the T-SQL perspective. They appear in the sys.external_tables catalog view rather than sys.tables. This matters when writing metadata queries or when tools try to enumerate warehouse objects — you may need to query both catalog views to get a complete picture.
Now for the payoff. Open a new SQL query in your warehouse editor. The shortcut tables are immediately queryable with standard T-SQL syntax:
-- Basic validation: count rows and check the data range
SELECT
COUNT(*) AS total_transactions,
SUM(sale_amount) AS total_revenue,
MIN(sale_date) AS first_sale,
MAX(sale_date) AS last_sale
FROM dbo.fact_sales;
This reads directly from the Delta Parquet files in the retail_gold lakehouse. No data was moved. The warehouse T-SQL engine translates the query into a scan of the Parquet files through the shortcut path.
Now let's write the cross-engine query that justifies this whole architecture — joining the shortcut-backed lakehouse tables against the warehouse-native finance table:
SELECT
dp.category_name,
dp.subcategory_name,
dc.region,
DATEPART(YEAR, fs.sale_date) AS sale_year,
DATEPART(QUARTER, fs.sale_date) AS sale_quarter,
SUM(fs.sale_amount) AS actual_revenue,
MAX(bt.revenue_target) AS budget_target,
SUM(fs.sale_amount) - MAX(bt.revenue_target) AS variance,
ROUND(
(SUM(fs.sale_amount) / NULLIF(MAX(bt.revenue_target), 0)) * 100,
2
) AS pct_of_target
FROM
dbo.fact_sales AS fs
INNER JOIN dbo.dim_product AS dp ON fs.product_key = dp.product_key
INNER JOIN dbo.dim_customer AS dc ON fs.customer_key = dc.customer_key
INNER JOIN finance.budget_targets AS bt
ON dp.category_name = bt.category_name
AND dc.region = bt.region
AND DATEPART(YEAR, fs.sale_date) = bt.fiscal_year
AND DATEPART(QUARTER, fs.sale_date) = bt.fiscal_quarter
GROUP BY
dp.category_name,
dp.subcategory_name,
dc.region,
DATEPART(YEAR, fs.sale_date),
DATEPART(QUARTER, fs.sale_date)
ORDER BY
sale_year,
sale_quarter,
actual_revenue DESC;
In this query, dbo.fact_sales, dbo.dim_product, and dbo.dim_customer are all shortcut-backed Delta tables from the lakehouse. finance.budget_targets is a native warehouse table. The T-SQL engine joins them as though they're all local — because from the storage perspective, they effectively are.
Key insight
The warehouse query optimizer treats shortcut tables similarly to external tables when building execution plans. This means predicate pushdown works for simple column filters — if you filter WHERE fs.sale_date >= '2024-01-01', the engine will skip Parquet row groups that don't match based on Delta statistics. However, complex join-pushdown optimizations that work across warehouse-native tables may not apply to shortcut tables. Design your queries to filter shortcut tables early and join results to native tables last.
Direct references to shortcut table names in application queries are fine for ad-hoc work, but in production you should abstract the access through views. This gives you flexibility to change the underlying shortcut path or replace a shortcut with a native copy (if, say, you decide the performance trade-off isn't worth it) without changing every downstream query.
-- Create a reporting schema to hold the business-facing views
CREATE SCHEMA reporting;
GO
-- Wrap the shortcut tables in views with business-friendly column names
CREATE VIEW reporting.vw_sales_actuals AS
SELECT
fs.sale_transaction_id,
fs.sale_date,
fs.sale_amount,
fs.quantity_sold,
fs.discount_pct,
dp.product_name,
dp.category_name,
dp.subcategory_name,
dp.unit_cost,
dc.customer_name,
dc.region,
dc.segment
FROM
dbo.fact_sales AS fs
INNER JOIN dbo.dim_product AS dp ON fs.product_key = dp.product_key
INNER JOIN dbo.dim_customer AS dc ON fs.customer_key = dc.customer_key;
GO
-- The budget vs actuals report can now reference clean view names
CREATE VIEW reporting.vw_budget_vs_actuals AS
SELECT
sa.category_name,
sa.region,
DATEPART(YEAR, sa.sale_date) AS sale_year,
DATEPART(QUARTER, sa.sale_date) AS sale_quarter,
SUM(sa.sale_amount) AS actual_revenue,
MAX(bt.revenue_target) AS budget_target,
SUM(sa.sale_amount) - MAX(bt.revenue_target) AS variance
FROM
reporting.vw_sales_actuals AS sa
INNER JOIN finance.budget_targets AS bt
ON sa.category_name = bt.category_name
AND sa.region = bt.region
AND DATEPART(YEAR, sa.sale_date) = bt.fiscal_year
AND DATEPART(QUARTER, sa.sale_date) = bt.fiscal_quarter
GROUP BY
sa.category_name,
sa.region,
DATEPART(YEAR, sa.sale_date),
DATEPART(QUARTER, sa.sale_date);
GO
Now analysts can run SELECT * FROM reporting.vw_budget_vs_actuals WHERE sale_year = 2024 without knowing anything about shortcuts, Delta tables, or the underlying architecture. If you later decide to materialize the sales data into the warehouse for performance reasons, you swap out the view definition — the analyst's query doesn't change.
This approach also integrates cleanly with building a Fabric data warehouse with T-SQL, where views and cross-database query patterns are discussed in depth.
Here's something that surprises many practitioners: when the lakehouse schema changes — new columns added, columns renamed — the warehouse shortcut does not automatically reflect those changes. The shortcut still points to the correct Parquet files, but the warehouse's internal metadata cache for the external table may be stale.
If someone adds a promotion_code column to fact_sales in the lakehouse via a PySpark notebook, and you immediately run:
SELECT promotion_code FROM dbo.fact_sales;
...you may get an error like "Invalid column name 'promotion_code'" even though the data physically contains that column.
To refresh the warehouse's metadata for a shortcut table, you need to trigger a sync. In the current Fabric warehouse experience, you can do this by:
Alternatively, you can drop and recreate the shortcut to force a full schema refresh:
-- Check current column definitions for the shortcut table
SELECT
c.name AS column_name,
t.name AS data_type,
c.max_length,
c.is_nullable
FROM
sys.external_tables AS et
INNER JOIN sys.columns AS c ON et.object_id = c.object_id
INNER JOIN sys.types AS t ON c.user_type_id = t.user_type_id
WHERE
et.name = 'fact_sales'
ORDER BY c.column_id;
If the column count doesn't match what you know is in the Delta table, you need a metadata refresh.
Warning
If your lakehouse table undergoes schema changes frequently (for example, you're in active development and columns are being added or restructured regularly), build a metadata refresh step into your pipeline orchestration. You can trigger a warehouse metadata refresh programmatically via the Fabric REST API as a pipeline activity. Don't rely on analysts manually noticing stale column definitions — they'll just assume the column doesn't exist.
Schema evolution patterns in your Delta tables — and how to manage them across medallion layers — are covered in detail in the handling schema evolution in Fabric lakehouse Delta tables article.
Security for shortcuts is one of the most common sources of confusion, so let's be explicit about how it works.
Same-workspace shortcuts are the simplest case. If your retail_gold lakehouse and retail_warehouse warehouse are in the same Fabric workspace, any user with at least Viewer role on the workspace can read the shortcut data in the warehouse (assuming they have read access to the warehouse itself). The workspace identity automatically has access to read from both items.
Cross-workspace shortcuts require more deliberate setup. If the lakehouse lives in a Data Engineering workspace and the warehouse lives in a Finance Analytics workspace, the warehouse's managed identity must be granted at least Read access to the lakehouse item in the Data Engineering workspace. Without this, the shortcut creation succeeds (it's just a metadata pointer), but queries against the shortcut will fail at runtime with an access denied error — which is particularly confusing because the error appears during query execution, not during shortcut creation.
To grant this access:
Data Engineering workspaceretail_gold lakehouse's settingsWarning
Don't confuse workspace role permissions with item-level permissions. A user can have the Viewer role on the Finance Analytics workspace — giving them the ability to query the warehouse — without having any access to the Data Engineering workspace. For cross-workspace shortcuts, you need to explicitly grant item-level read access to the lakehouse. If you skip this step, queries will silently fail for affected users even though the shortcut appears healthy in the warehouse.
Row-level security defined on the lakehouse SQL analytics endpoint does not automatically propagate through the warehouse shortcut. If you have RLS policies on fact_sales in the lakehouse, those policies apply when users query through the lakehouse's SQL endpoint — but when users query dbo.fact_sales in the warehouse through the shortcut, they bypass those lakehouse-level policies. You need to implement equivalent RLS directly in the warehouse if the security requirement applies to warehouse consumers. This is covered thoroughly in the implementing row-level security in a Fabric warehouse guide.
You've seen that shortcuts enable zero-copy cross-engine queries, but that doesn't mean performance is free. Here's what to understand about the trade-offs.
What works well:
fact_sales is partitioned by sale_date, a query like WHERE sale_date >= '2024-Q1-01' will use partition pruning and skip large swaths of data. This is because the warehouse reads the Delta transaction log to understand partition layout.What to watch:
WHERE transaction_id = 'TXN-8472921' will scan all Parquet files unless the Delta table has Z-Order applied on that column. See the Delta table performance optimization guide for how to address this at the lakehouse layer.When to use shortcuts vs materializing into the warehouse:
| Scenario | Recommendation |
|---|---|
| Gold layer data is authoritative and already well-optimized | Shortcut — no duplication needed |
| Finance team needs pure T-SQL with stored procedures | Shortcut works; add views to abstract |
| Highly selective point-lookup queries (e.g., order lookup by ID) | Consider materializing; shortcuts favor scans |
| Data must be visible in warehouse within seconds of lakehouse write | Shortcut — no sync lag |
| Regulatory requirement that warehouse contains a self-contained copy | Materialize — shortcuts are read-through |
| Complex aggregations with many joins between large tables | Test both; shortcuts may be adequate with OPTIMIZE |
In this exercise, you'll build the complete shortcut-based cross-engine query pattern using a realistic dataset.
Setup: Create a lakehouse called sales_gold and a warehouse called analytics_warehouse in the same workspace.
Step 1: Create the lakehouse tables using a Spark notebook.
Open a notebook attached to sales_gold and run:
from pyspark.sql import SparkSession
from pyspark.sql.types import *
from pyspark.sql.functions import *
import random
from datetime import date, timedelta
spark = SparkSession.builder.getOrCreate()
# Generate a realistic dim_store table
store_data = [
(1, "Chicago Downtown", "Chicago", "IL", "Midwest", "Tier 1"),
(2, "Chicago Oak Park", "Chicago", "IL", "Midwest", "Tier 2"),
(3, "Houston Galleria", "Houston", "TX", "South", "Tier 1"),
(4, "Houston Midtown", "Houston", "TX", "South", "Tier 2"),
(5, "Seattle Capitol Hill", "Seattle", "WA", "West", "Tier 1"),
(6, "Seattle Bellevue", "Seattle", "WA", "West", "Tier 2"),
(7, "New York Midtown", "New York", "NY", "Northeast", "Tier 1"),
(8, "New York Brooklyn", "New York", "NY", "Northeast", "Tier 2"),
]
store_schema = StructType([
StructField("store_key", IntegerType(), False),
StructField("store_name", StringType(), False),
StructField("city", StringType(), False),
StructField("state", StringType(), False),
StructField("region", StringType(), False),
StructField("store_tier", StringType(), False),
])
dim_store_df = spark.createDataFrame(store_data, store_schema)
dim_store_df.write.format("delta").mode("overwrite").saveAsTable("dim_store")
# Generate fact_daily_sales with 2 years of data
categories = ["Electronics", "Apparel", "Home & Garden", "Sports", "Beauty"]
base_date = date(2023, 1, 1)
sales_rows = []
for day_offset in range(730): # 2 years
sale_date = base_date + timedelta(days=day_offset)
for store_key in range(1, 9):
for cat_idx, category in enumerate(categories):
revenue = round(random.uniform(5000, 95000), 2)
txn_count = random.randint(50, 800)
sales_rows.append((
f"S{day_offset:04d}T{store_key}C{cat_idx}",
sale_date.isoformat(),
store_key,
category,
revenue,
txn_count,
round(revenue / txn_count, 2)
))
sales_schema = StructType([
StructField("sale_id", StringType(), False),
StructField("sale_date", StringType(), False),
StructField("store_key", IntegerType(), False),
StructField("category", StringType(), False),
StructField("daily_revenue", DoubleType(), False),
StructField("transaction_count",IntegerType(), False),
StructField("avg_basket_size", DoubleType(), False),
])
fact_df = spark.createDataFrame(sales_rows, sales_schema)
fact_df = fact_df.withColumn("sale_date", col("sale_date").cast("date"))
# Write partitioned by year and month for query performance
fact_df.write \
.format("delta") \
.mode("overwrite") \
.partitionBy("sale_date") \
.saveAsTable("fact_daily_sales")
print(f"Created fact_daily_sales with {fact_df.count():,} rows")
print("Created dim_store with 8 stores")
Step 2: Create a budget targets table in the warehouse.
Open analytics_warehouse and run this in the SQL editor:
CREATE SCHEMA planning;
GO
CREATE TABLE planning.store_budget (
budget_id INT IDENTITY(1,1) PRIMARY KEY,
region VARCHAR(50) NOT NULL,
category VARCHAR(100) NOT NULL,
fiscal_year INT NOT NULL,
fiscal_quarter INT NOT NULL,
revenue_target DECIMAL(18,2) NOT NULL,
created_at DATETIME2 DEFAULT GETUTCDATE()
);
INSERT INTO planning.store_budget (region, category, fiscal_year, fiscal_quarter, revenue_target)
VALUES
('Midwest', 'Electronics', 2024, 1, 1250000.00),
('Midwest', 'Electronics', 2024, 2, 1380000.00),
('Midwest', 'Electronics', 2024, 3, 1450000.00),
('Midwest', 'Electronics', 2024, 4, 1900000.00),
('Midwest', 'Apparel', 2024, 1, 890000.00),
('Midwest', 'Apparel', 2024, 2, 920000.00),
('Midwest', 'Apparel', 2024, 3, 950000.00),
('Midwest', 'Apparel', 2024, 4, 1200000.00),
('South', 'Electronics', 2024, 1, 1100000.00),
('South', 'Electronics', 2024, 2, 1200000.00),
('South', 'Electronics', 2024, 3, 1300000.00),
('South', 'Electronics', 2024, 4, 1750000.00),
('West', 'Electronics', 2024, 1, 1050000.00),
('West', 'Apparel', 2024, 1, 780000.00),
('Northeast', 'Electronics', 2024, 1, 1400000.00),
('Northeast', 'Apparel', 2024, 1, 980000.00);
Step 3: Create the shortcuts. Follow the steps from earlier in this lesson to create shortcuts in analytics_warehouse pointing to fact_daily_sales and dim_store in sales_gold.
Step 4: Write the cross-engine analysis query.
-- Actual vs budget by region and category for 2024
WITH actuals AS (
SELECT
ds.region,
fds.category,
YEAR(fds.sale_date) AS fiscal_year,
DATEPART(QUARTER, fds.sale_date) AS fiscal_quarter,
SUM(fds.daily_revenue) AS actual_revenue,
SUM(fds.transaction_count) AS total_transactions
FROM
dbo.fact_daily_sales AS fds
INNER JOIN dbo.dim_store AS ds ON fds.store_key = ds.store_key
WHERE
YEAR(fds.sale_date) = 2024
GROUP BY
ds.region,
fds.category,
YEAR(fds.sale_date),
DATEPART(QUARTER, fds.sale_date)
)
SELECT
a.region,
a.category,
a.fiscal_year,
a.fiscal_quarter,
ROUND(a.actual_revenue, 2) AS actual_revenue,
b.revenue_target,
ROUND(a.actual_revenue - b.revenue_target, 2) AS variance,
ROUND((a.actual_revenue / NULLIF(b.revenue_target,0)) * 100, 1) AS pct_attainment,
a.total_transactions,
CASE
WHEN a.actual_revenue >= b.revenue_target THEN 'On Target'
WHEN a.actual_revenue >= b.revenue_target * 0.9 THEN 'Near Target'
ELSE 'Below Target'
END AS performance_band
FROM
actuals AS a
LEFT JOIN planning.store_budget AS b
ON a.region = b.region
AND a.category = b.category
AND a.fiscal_year = b.fiscal_year
AND a.fiscal_quarter = b.fiscal_quarter
ORDER BY
a.fiscal_quarter,
a.region,
a.category;
This query spans both engines: fact_daily_sales and dim_store are Delta tables from the lakehouse accessed via shortcuts; planning.store_budget is a native warehouse table. Both are queryable in one T-SQL statement with no data duplication.
"Invalid object name 'dbo.fact_daily_sales'" after creating the shortcut
The shortcut was created but the warehouse metadata sync hasn't completed. Wait 30-60 seconds after creating the shortcut and refresh the object explorer. If the table still doesn't appear, navigate away from the warehouse and return — this forces a metadata reload. If the problem persists, verify the Delta table is readable from the lakehouse SQL analytics endpoint first.
Query returns no rows but the lakehouse table has data
This almost always means the shortcut is pointing to the correct path but the Delta log is empty or the table files are in the Files section rather than the Tables section. In the lakehouse, only items under Tables are managed Delta tables. Files dropped into the Files section are raw and cannot be shortcutted as tables into the warehouse.
"Access denied" errors at query time despite the shortcut appearing healthy
For cross-workspace shortcuts, this is the missing item-level permission on the source lakehouse. For same-workspace shortcuts, check that the user querying the warehouse has at least Viewer access on the workspace — direct warehouse item permissions alone aren't sufficient to read through a shortcut to a lakehouse in the same workspace.
New columns from the lakehouse are missing in warehouse queries
Metadata cache is stale. Trigger a metadata refresh from the warehouse toolbar, or drop and recreate the shortcut. Build metadata refresh into your pipeline's post-processing steps when schema changes are expected.
Queries against shortcut tables are slow despite the lakehouse queries being fast
Check whether your Delta table has been OPTIMIZE'd recently. Also verify partition pruning is happening by examining the query plan — filter conditions on the partition column must be explicit and constant (not derived from a subquery) for partition elimination to kick in. Consider materializing heavily-queried aggregations into native warehouse tables using CREATE TABLE AS SELECT patterns and refreshing them on a schedule.
Stored procedures referencing shortcut tables fail to compile
Fabric Warehouse stored procedures can reference shortcut tables, but the table must exist at the time the procedure is compiled. If you drop and recreate a shortcut (for a metadata refresh), stored procedures that reference it need to be recompiled. Use EXEC sp_recompile 'your_procedure_name' after recreating shortcuts that stored procedures depend on.
You've built the complete pattern: Delta tables authored in a Fabric Lakehouse, shortcuts created in a Fabric Warehouse that redirect reads to those Delta files through OneLake, and T-SQL queries that transparently join shortcut-backed external tables with warehouse-native tables — all without duplicating a single byte of data.
The key principles to carry forward:
sys.external_tables and sys.tables for complete object enumeration.Where to go from here: