Back to Insights

Automating Microsoft Fabric & Power BI Governance

How programmatically orchestrating Python scripts, WorkspaceScan endpoints, and semantic model validations saves thousands of dollars in Microsoft Fabric Capacity throttling.

A primary issue we consistently observe in business intelligence environments—especially as enterprises migrate from Power BI Premium per Capacity to Azure-backed Microsoft Fabric Capacities (F-SKUs)—is that costs can spiral entirely out of control if you leave developers without strict deployment and query guardrails.

Microsoft Fabric operates on a Capacity Unit (CU) model. Every second of DAX evaluation, every excessive iterator (FILTER, SUMX inside huge nested contexts), and every unoptimized measure burns capacity. If your models aren’t properly managed, your capacity gets throttled. The common instinct is to buy more capacity. The correct instinct is to implement programmatic governance.

The Problem With Manual Governance

Historically, ensuring a semantic model was healthy meant firing up tabular editor (Tabular Editor 2 or 3), running the Best Practice Analyzer (BPA) macros locally, and doing ad-hoc investigations. It simply doesn’t scale.

When you manage dozens of workspaces spanning multiple production environments, hoping that individual developers remember to hide foreign keys and swap FILTER(Table) for boolean predicates isn’t an architectural strategy; it’s a prayer.

Our Approach: The Automated Catalog

At Montinegro Corp, we shifted governance from a reactive, manual step into a proactive, automated pipeline relying heavily on Python automation. This system actively guards our, and our clients’, Fabric tenants.

1. Extracting Intelligence via the Power BI REST API

We maintain an evolving internal catalog of Python scripts directly built to interact with the Power BI Admin REST APIs (specifically endpoints like WorkspaceInfo and Scanner).

Rather than manually checking workspaces, we execute scheduled jobs that parse the entire topology of the Power BI tenant into memory. This provides deep structural insight without needing to explicitly query the models.

2. Live DAX Queries via Python (ExecuteQueries Endpoint)

By securing implicit connections using Entra ID (via az cli tokens within sandboxed environments), we trigger custom DAX expressions directly from our code, hitting the datasets/{datasetId}/executeQueries endpoints. This means we can periodically check standard query speeds across live multi-million row datasets to measure potential degradation before a user complains.

3. Automated DMV Scanning (Dynamic Management Views)

Governance is more than speed—it’s hygiene. Our orchestration pings the underlying Analysis Services engines via DMVs to detect massive red flags:

  • Are there unhidden dimensions serving as primary keys breaking down interface logic?
  • Are data types mismatched causing huge DAX engine memory bloats?
  • Are excessive bi-directional cross-filtering relationships in place, breaking standard star-schema logic?

Our Python stack automatically parses these XMLA or DMV readouts, categorizes the offenses, and shoots reports before the specific PowerBI .pbip commit ever hits the main branch.

4. Integration with CI/CD

This is where the magic fully materializes. By pushing .pbip (Power BI Project) files into GitHub, we attach these exact Python scanning jobs as GitHub Actions. If a developer attempts to commit an unoptimized model with missing cardinality rules, the CI/CD pipeline correctly identifies the failure and rejects the Pull Request down the line.

Conclusion

Throwing cash at an oversized Fabric F-SKU to hide terrible data modeling is the fastest path to unprofitability. By injecting code-first infrastructure—treating Power BI semantic models merely as structural endpoints to be interrogated by Python automation—you regain total control over your cloud spending and semantic health.