Um problema primário que observamos consistentemente em ambientes de business intelligence — especialmente conforme empresas migram de Power BI Premium per Capacity para Microsoft Fabric Capacities (F-SKUs) backed por Azure — é que os custos podem espiralar completamente fora de controle se você deixar desenvolvedores sem guardrails estritos de deploy e query.
Microsoft Fabric opera em um modelo de Capacity Units (CU). Cada segundo de avaliação DAX, cada iterador excessivo (FILTER, SUMX dentro de contextos aninhados enormes), e cada medida não-otimizada queima capacidade. Se seus modelos não estão propriamente gerenciados, sua capacidade sofre throttling. O instinto comum é comprar mais capacidade. O instinto correto é implementar governança programática.
O Problema da Governança Manual
Historicamente, garantir que um modelo semântico estava saudável significava abrir o Tabular Editor (2 ou 3), rodar as macros do Best Practice Analyzer (BPA) localmente, e fazer investigações ad-hoc. Simplesmente não escala.
Quando você gerencia dezenas de workspaces em múltiplos ambientes de produção, esperar que desenvolvedores individuais lembrem de esconder foreign keys e trocar FILTER(Table) por predicados booleanos não é uma estratégia arquitetural; é uma reza.
O Custo Real da Negligência
É assim que modelos semânticos descontrolados se manifestam em produção:
- Throttling de capacidade: Uma única medida DAX mal escrita iterando sobre uma tabela fato de 50M linhas pode consumir 30-40% de uma F4 durante horários de pico
- Slowdowns em cascata: Quando o refresh de um workspace dispara throttling, cada workspace naquela capacidade sofre — finanças, operações, vendas, todos congelados
- Upsizing emergencial: Comprar F8 ou F16 em pânico para compensar modelagem ruim facilmente adiciona R$ 10.000-40.000/mês de gasto desnecessário
- Shadow IT: Usuários frustrados exportam para Excel e constroem suas próprias análises, minando o investimento inteiro em BI
O gap entre “temos Power BI” e “temos Power BI governado” é tipicamente 5-10x em custo operacional.
Nossa Abordagem: O Catálogo Automatizado
Na Montinegro Corp, deslocamos governança de um passo reativo e manual para um pipeline proativo e automatizado dependendo fortemente de automação Python. Este sistema ativamente protege os tenants Fabric nossos e dos nossos clientes.
Mantemos um catálogo interno de scripts Python especializados — cada um mirando um domínio específico de governança — que rodam agendados ou sob demanda contra o backend do Power BI.
1. Extraindo Inteligência via Power BI REST API
Mantemos um catálogo em evolução de scripts Python construídos para interagir com as Power BI Admin REST APIs (especificamente endpoints como WorkspaceInfo e Scanner).
Ao invés de checar workspaces manualmente, executamos jobs agendados que parseiam a topologia inteira do tenant Power BI em memória. Isso provê insight estrutural profundo sem precisar consultar os modelos explicitamente.
Um scan típico produz:
Workspace: PRD_COMERCIAL
├─ Dataset: DSN_VENDAS_REGIONAL (45 tabelas, 23 medidas)
│ ├─ Último refresh: 2026-04-24 06:15:00 UTC (Sucesso)
│ ├─ Memória configurada: 2.4 GB
│ └─ Endorsement: Certificado
├─ Dataset: DSN_META_FORECAST (12 tabelas, 8 medidas)
│ ├─ Último refresh: 2026-04-24 06:30:00 UTC (Falha)
│ └─ Erro: Timeout na partição MART_FORECAST_DETAIL
└─ Relatórios: 14 (3 órfãos - sem binding de dataset)
Esses dados alimentam alertas automatizados. Refreshes falhados disparam investigação imediata. Relatórios órfãos são sinalizados para cleanup.
2. Queries DAX ao Vivo via Python (Endpoint ExecuteQueries)
Protegendo conexões implícitas usando Entra ID (via tokens do az cli em ambientes sandboxed), disparamos expressões DAX customizadas diretamente do nosso código, atingindo os endpoints datasets/{datasetId}/executeQueries. Isso significa que podemos periodicamente checar velocidades de query padrão em datasets ao vivo com milhões de linhas para medir degradação potencial antes que um usuário reclame.
Rodamos queries DAX de benchmark em schedule:
benchmark_queries = {
"agregacao_simples": "EVALUATE ROW(\"Total\", [Total Sales])",
"time_intelligence": "EVALUATE ROW(\"YTD\", [Sales YTD])",
"filtro_complexo": """
EVALUATE
CALCULATETABLE(
SUMMARIZECOLUMNS(
'Product'[Category],
"Revenue", [Total Sales],
"Margin", [Gross Margin %]
),
'Calendar'[Year] = 2026
)
"""
}
Cada query é cronometrada. Se agregacao_simples que normalmente completa em 120ms de repente leva 800ms, sabemos que algo mudou no modelo ou a capacidade está sob pressão. Isso captura regressões de performance antes de usuários abrirem chamados.
3. Scanning Automatizado de DMVs (Dynamic Management Views)
Governança é mais que velocidade — é higiene. Nossa orquestração consulta os engines Analysis Services subjacentes via DMVs para detectar red flags massivos:
- Existem dimensões não-escondidas servindo como primary keys que quebram a lógica de interface?
- Existem data types incompatíveis causando bloats de memória no engine DAX?
- Existem relacionamentos cross-filtering bidirecionais excessivos quebrando lógica padrão de star-schema?
- Existem colunas não-utilizadas consumindo memória sem aparecer em nenhuma medida ou visual?
Nosso stack Python automaticamente parseia esses readouts XMLA ou DMV, categoriza as ofensas por severidade, e gera relatórios estruturados.
Classificação de Severidade
| Nível | Issue | Exemplo | Impacto |
|---|---|---|---|
| Crítico | Relacionamentos bidirecionais | Fato ↔ Dimensão com ambiguidade | Vazamento de filtros de segurança, cálculos errados |
| Alto | Colunas FK não-escondidas | CustomerID visível na lista de campos | Confusão do usuário, agregação acidental |
| Médio | Sort-by-column faltando | Nome do mês sem ordem de classificação | Ordenação visual incorreta |
| Baixo | Colunas não-utilizadas | Colunas importadas em nenhuma medida/visual | Memória desperdiçada, refreshes mais lentos |
Relatórios são gerados como tabelas Markdown que alimentam diretamente nossos dashboards de monitoramento e alertas no Slack.
4. Integração com CI/CD
É aqui que o sistema de governança atinge seu potencial completo. Ao fazer push de arquivos .pbip (Power BI Project) no GitHub, acoplamos esses mesmos jobs Python de scanning como GitHub Actions.
O workflow:
- Desenvolvedor cria ou modifica um modelo semântico localmente
- Faz commit do arquivo de projeto
.pbipem uma feature branch - Um Pull Request dispara checks automatizados de CI:
- Validação de schema: Todas as tabelas seguem convenções de nomenclatura?
- Regras BPA: O modelo passa em todos os checks do Best Practice Analyzer?
- Auditoria de relacionamentos: Algum bidirecional ou many-to-many sem justificativa?
- Qualidade de medidas: Existem padrões FILTER(Table) que deveriam ser predicados?
- Se qualquer check falha, o PR é bloqueado com feedback detalhado
- Se todos passam, o modelo é aprovado para merge na
main - Pós-merge, o pipeline de deploy publica o modelo no workspace alvo
Isso significa que enforcement de governança acontece antes de um modelo ruim chegar à produção. Desenvolvedores recebem feedback instantâneo e específico: “Linha 47 de measures.dax: Substitua FILTER(Sales, Sales[Region] = "East") por Sales[Region] = "East" como predicado direto para melhoria de performance de 3-5x.”
5. Monitoramento e Alertas de Capacidade
Além da governança a nível de modelo, monitoramos continuamente padrões de utilização de capacidade:
- Tendências de consumo de CU: Estamos nos aproximando do threshold de smoothing de 24 horas?
- Split background vs. interativo: Refreshes agendados estão competindo com queries de usuários?
- Eventos de throttling: Quando o throttling começou, quais operações dispararam, e qual foi o blast radius?
Puxamos esses dados do app Fabric Capacity Metrics e aumentamos com nossa própria telemetria. O objetivo é nunca ser surpreendido por um problema de capacidade — quando um usuário nota lentidão, já deveríamos saber o porquê e estar trabalhando na correção.
O Framework de ROI
Para uma empresa mid-market típica rodando 20-50 workspaces em uma capacidade F4 (R$ 25.000/mês):
Antes da governança automatizada:
- 2-3 eventos de throttling por semana
- Média de 45 minutos de performance degradada por evento
- 1 upgrade emergencial para F8 por trimestre (R$ 50.000/mês de gasto temporário)
- 8-12 horas/mês de revisões BPA manuais por desenvolvedores sêniores
Depois da governança automatizada:
- 0-1 eventos de throttling por mês
- Issues capturados no estágio de PR, não em produção
- Capacidade F4 estável sem upgrades emergenciais
- 0 horas de revisões manuais (totalmente automatizado)
Economia anual estimada: R$ 200.000-400.000 em custos de capacidade apenas, mais 100-150 horas de tempo de desenvolvedor recuperado.
O Que Não Automatizamos
Nem tudo deveria ser código. Convenções de nomenclatura e padrões arquiteturais requerem julgamento humano durante o design inicial. Políticas de acesso a dados precisam de input de stakeholders de negócio. A decisão de promover um dataset de Desenvolvimento para Certificado envolve confiança e validação que nenhum script consegue substituir completamente.
Nossa automação cuida do enforcement mecânico. Humanos cuidam das decisões estratégicas. A linha entre os dois deve ser deliberada, não acidental.
Implementação
Jogar dinheiro em um F-SKU Fabric superdimensionado para esconder modelagem de dados terrível é o caminho mais rápido para a não-lucratividade. Ao injetar infraestrutura code-first — tratando modelos semânticos Power BI como endpoints estruturais a serem interrogados por automação Python — você retoma controle total sobre seu gasto cloud e saúde semântica.
As ferramentas existem. As APIs estão documentadas. A questão é se sua organização trata governança como um adendo ou como infraestrutura.