microsoft/direct-lake-operations
Guide for working with Direct Lake semantic models. Use this when implementing Direct Lake-related features or troubleshooting.
npx skills add https://github.com/microsoft/semantic-link-labs --skill direct-lake-operations
This skill covers working with Direct Lake semantic models in Semantic Link Labs.
Use this skill when you need to:
Direct Lake is a storage mode for Power BI semantic models that reads data directly from Delta tables in OneLake, providing fast query performance without data import.
| File | Purpose |
|------|---------|
| src/sempy_labs/directlake/ | Direct Lake submodule |
| _dl_helper.py | Core Direct Lake utilities |
| _guardrails.py | Guardrail checking |
| _directlake_schema_sync.py | Schema synchronization |
| _warm_cache.py | Cache warming utilities |
| Function | Purpose |
|----------|---------|
| check_fallback_reason | Check why model falls back to DirectQuery |
| get_direct_lake_lakehouse | Get lakehouse connected to model |
| get_direct_lake_source | Get SQL endpoint and lakehouse info |
| generate_direct_lake_semantic_model | Create new Direct Lake model |
| Function | Purpose |
|----------|---------|
| direct_lake_schema_compare | Compare model schema with lakehouse |
| direct_lake_schema_sync | Sync model schema from lakehouse |
| Function | Purpose |
|----------|---------|
| get_direct_lake_guardrails | Get guardrail limits for model |
| get_sku_size | Get SKU capacity info |
| get_directlake_guardrails_for_sku | Get guardrails for specific SKU |
| Function | Purpose |
|----------|---------|
| warm_direct_lake_cache_isresident | Warm cache using IsResident |
| warm_direct_lake_cache_perspective | Warm cache using perspective |
| Function | Purpose |
|----------|---------|
| update_direct_lake_model_connection | Update lakehouse connection |
| update_direct_lake_model_lakehouse_connection | Legacy connection update |
Direct Lake models can fall back to DirectQuery mode. Use check_fallback_reason to diagnose:
from sempy_labs.directlake import check_fallback_reason
# Check specific model
result = check_fallback_reason(
dataset="My Direct Lake Model",
workspace="My Workspace"
)
# Returns DataFrame with fallback reasons per table
print(result)
| Reason | Cause | Solution |
|--------|-------|----------|
| ColumnNotInPartition | Column missing from Delta table | Add column to lakehouse table |
| ParquetTypeMismatch | Data type mismatch | Update lakehouse table schema |
| UnsupportedFilter | DAX filter not supported | Modify DAX query |
| Guardrail | Exceeded capacity limits | Upgrade capacity or reduce data |
from sempy_labs.directlake import direct_lake_schema_compare
# Compare model schema with lakehouse tables
comparison = direct_lake_schema_compare(
dataset="My Direct Lake Model",
workspace="My Workspace"
)
# Shows differences between model and lakehouse
print(comparison)
from sempy_labs.directlake import direct_lake_schema_sync
# Sync model schema from lakehouse
direct_lake_schema_sync(
dataset="My Direct Lake Model",
workspace="My Workspace",
add_columns=True, # Add new columns
remove_columns=False, # Keep columns not in lakehouse
)
Direct Lake has limits based on capacity SKU:
from sempy_labs.directlake import get_direct_lake_guardrails
# Get guardrails for a model
guardrails = get_direct_lake_guardrails(
dataset="My Direct Lake Model",
workspace="My Workspace"
)
# Shows limits vs current values
print(guardrails)
| Guardrail | Description |
|-----------|-------------|
| Max Rows Per Table | Maximum rows per table |
| Max Size Per Table | Maximum table size in GB |
| Max Columns Per Table | Maximum columns per table |
| Max Model Size | Maximum total model size |
Create a new Direct Lake model from lakehouse tables:
from sempy_labs.directlake import generate_direct_lake_semantic_model
# Generate model from lakehouse
generate_direct_lake_semantic_model(
dataset="New Direct Lake Model",
lakehouse="My Lakehouse",
workspace="My Workspace",
lakehouse_workspace="Lakehouse Workspace", # Optional
)
Change the lakehouse a Direct Lake model points to:
from sempy_labs.directlake import update_direct_lake_model_connection
# Update to different lakehouse
update_direct_lake_model_connection(
dataset="My Direct Lake Model",
workspace="My Workspace",
target_lakehouse="New Lakehouse",
target_workspace="Target Workspace",
)
Warm the Direct Lake cache after model refresh:
from sempy_labs.directlake import warm_direct_lake_cache_isresident
# Warm columns that were previously in memory
warm_direct_lake_cache_isresident(
dataset="My Direct Lake Model",
workspace="My Workspace"
)
from sempy_labs.directlake import warm_direct_lake_cache_perspective
# Warm columns defined in a perspective
warm_direct_lake_cache_perspective(
dataset="My Direct Lake Model",
perspective="Cache Warming",
workspace="My Workspace"
)
The library provides migration tools in src/sempy_labs/migration/:
from sempy_labs.migration import (
migrate_calctables_to_lakehouse,
migrate_model_objects_to_semantic_model,
)
# Step 1: Migrate calculated tables to lakehouse
migrate_calctables_to_lakehouse(
dataset="Source Import Model",
workspace="My Workspace",
lakehouse="Target Lakehouse",
lakehouse_workspace="Lakehouse Workspace",
)
# Step 2: Migrate other objects (measures, etc.)
migrate_model_objects_to_semantic_model(
source_dataset="Source Import Model",
target_dataset="Target Direct Lake Model",
source_workspace="My Workspace",
target_workspace="My Workspace",
)
check_fallback_reason() to identify causedirect_lake_schema_compare()get_direct_lake_guardrails()direct_lake_schema_compare() to see differencesdirect_lake_schema_sync() to fix mismatcheswarm_direct_lake_cache_isresident()| Resource | URL |
|----------|-----|
| Direct Lake Overview | Microsoft Docs |
| Guardrails | Microsoft Docs |
| Migration Notebook | Notebook |
| API Docs | ReadTheDocs |
Take microsoft/direct-lake-operations from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.