How to use these
None of these has an answer that is always right; each depends on data volume, freshness, skills, licensing and who maintains it. Each comparison gives the conditions for each option, the trade-offs, how it fails, and a sensible default. When the decision matters, write it down as an ADR, including what would make you change your mind.
Import vs DirectQuery vs Direct Lake
Default: Import, until a requirement rules it out. Then Direct Lake if the data is in Fabric, DirectQuery (with aggregations) if it isn't. Practise: Composite models and DirectQuery, Direct Lake in depth.
Measure vs calculated column
- Trade-off: columns cost memory and refresh time; measures cost query time.
- Failure mode: calculated columns that use
CALCULATE over the fact table (slow refresh, confusing context transition); measures that try to be columns (SUMX everywhere to fake row logic). - Default: measure. If it must be a column, build it in Power Query or SQL instead of DAX.
Power Query vs SQL
- Failure mode: heavy joins and aggregations in Power Query that don't fold, so refresh drags all rows across the network.
- Default: as far upstream as is practical. See the full where-should-it-happen table.
Lakehouse vs Warehouse
- Trade-off: both store Delta in OneLake and both serve Direct Lake; the difference is how you write and who writes.
- Failure mode: choosing by fashion rather than by team skills; building the gold layer in a tool nobody on the team can maintain.
- Default: follow the team's language. Many designs use a Lakehouse for bronze and silver and a Warehouse for gold. See Fabric architecture.
Dataflow vs pipeline
- They aren't rivals: a pipeline often runs a dataflow, a notebook and a stored procedure in sequence.
- Failure mode: a chain of dataflows calling dataflows with no orchestration, monitoring or retry.
- Default: pipeline for movement and orchestration, dataflow (or notebook, or SQL) for the transformation.
One model vs multiple models
- Failure mode (too many): three "Revenue" measures with three answers (Sprint 05). Too few: a 200-table model nobody can change safely.
- Default: one certified model per business domain; reports connect to it with live connections.
RLS vs separate semantic models
- Failure mode: separate copies drift apart; RLS that nobody tests lets the wrong person see payroll (Sprint 03).
- Default: RLS (and OLS for columns), with a test matrix run every release. Separate models only when the audience must not even see the model's structure or when the data is legally segregated.
PBIX vs PBIP
- PBIX: personal analysis, one author, nothing to review.
- PBIP: anything a team maintains, anything in Git, anything deployed by a pipeline.
- Default: PBIP for shared content. See Ship Power BI like software.
Calculation group vs separate measures
- Failure mode: calculation groups with complex precedence that nobody can debug; format strings forgotten so "YoY %" shows as currency.
- Default: calculation groups once you'd otherwise write the same time logic for more than a handful of measures.
Shared semantic model vs a model inside each report
- Failure mode: every report file carries its own copy of the model, refreshes its own copy of the data, and drifts.
- Default: shared model with live-connected thin reports for anything that lasts.
Star vs snowflake
- Failure mode: snowflakes with bidirectional relationships to make filters flow up the chain.
- Default: star in the semantic model. Normalise in the warehouse if you like; flatten before Power BI.