A Power BI report can display persuasive charts while giving the wrong totals because its semantic model was built around ambiguous rows, duplicated relationships or poorly defined calculations. Modeling is the discipline of deciding what entities and events exist, how they relate and which filters should affect which measures. A good model allows different report pages to ask different questions without silently changing the definition of a sale, customer or delivery.
Consider a distribution company with order lines, warehouse dispatch events, product details, customers and changing delivery targets. Its management wants sales by category, shipments by region and late orders by month. The analysis will fail if an order line is joined directly to several dispatch scans and each line’s revenue is repeated for every scan. The model must begin by deciding the grain of the data.
Specify each fact table’s grain before adding relationships
The grain describes exactly what one fact row represents. A SalesLine table might contain one row per unique order line, with order-line amount and product key. A DispatchEvent table might contain one row per parcel scan, with the related order or parcel key and event timestamp. Those rows are not interchangeable: one sale may produce multiple dispatch events, and one parcel may be scanned several times.
Make the uniqueness rule explicit. SalesLineKey should identify one commercial line; DispatchEventKey should identify one observed scan. If a source provides no stable event identifier, resolve how duplicate records are recognized and tracked. Do not combine the datasets into one many-to-many tangle merely because both contain OrderID.
Separating the fact grains protects common calculations. The sum of SalesLine[NetAmount] can represent the amount associated with order lines after any defined adjustments. Counting DispatchEvent rows represents scans, not necessarily parcels delivered or distinct orders. A model that conflates those measures can overstate both revenue and operational volume.
Build a star schema around facts and dimensions
Dimensions describe entities used for filtering and grouping, such as Date, Product, Customer and Warehouse. Facts record observations or events, often referencing those dimensions through keys. A star schema positions descriptive dimension tables around fact tables so Power BI visuals can filter or group by one side of a relationship and summarize values on the other.
For example, Product[ProductKey] should be unique in the product dimension, while many SalesLine rows can share that key. This usually creates a one-to-many relationship. Product category becomes a coherent reporting attribute rather than text repeated thousands of times in each transaction row. Keep surrogate keys or durable business keys according to the data engineering contract, and check what happens when an upstream system reuses a code.
The Power Query preparation stage can split source exports into fact and dimension tables, normalize types and remove clear data defects. The modeling stage then decides how those prepared tables behave together. The two steps are complementary; a successful query load cannot prove the relationships are semantically correct.
Sometimes a snowflake dimension is warranted, but it adds relationship paths that report authors must understand. Microsoft’s guidance generally favors an optimized star schema for Power BI. Simplifying a small snowflake into a single descriptive dimension can improve usability where it does not destroy necessary business meaning. The aim is not a cosmetic star diagram but a clear, testable filtering structure.
Control cardinality and filter direction
Power BI relationships specify cardinality and cross-filter direction. A common, predictable configuration filters from the unique dimension side toward the many-row fact side. Set that direction deliberately rather than enabling bidirectional filtering everywhere to make a visual appear to work.
Bidirectional paths can create ambiguity when multiple facts or bridging tables connect. Consider warehouse and product dimensions connected through both sales and dispatch data. If filters can travel through every relationship in both directions, one visual may exclude rows that another visual includes, depending on the active path. Use a well-defined bridge or explicit DAX treatment only when the business question truly requires that structure.
When a many-to-many relationship is necessary, identify what each side means and whether the linking table represents a real association. A customer might belong to more than one sales region across time. Duplicating region assignments without effective dates can misstate historical totals. A factless bridging table may be appropriate, but it still needs tested keys, eligibility periods and filter behavior.
Relationships do not repair poor source grain. Before selecting a many-to-many option, check whether a supposed dimension has duplicate identifiers because of source errors or slowly changing records. Masking that defect in the relationship dialog may produce attractive visuals with the wrong denominator.
Handle dates and role-playing dimensions
Reporting by order date, shipment date and delivery date introduces multiple roles for calendar information. A Date dimension can be reused for several date relationships, but a model often has only one active relationship between a particular fact and shared date table for ordinary filter propagation. Additional inactive relationships require explicit measures, or the designer may create role-playing date dimensions to make each date purpose clear to report authors.
Decide what “Sales this month” means. Does it represent orders placed this month, orders shipped this month or revenue recognized this month? The answer is a business definition, not a DAX trick. Name measures and date roles so a report viewer is not asked to infer the difference from a chart title.
Time intelligence should use an appropriate date table with complete date coverage and correct date typing. It also requires careful treatment of fiscal calendars and incomplete periods. Comparing the first ten days of a month with a full prior month can create a dramatic but meaningless decline unless the periods are aligned.
Prefer explicit measures for business calculations
A measure such as Total Net Sales = SUM(SalesLine[NetAmount]) evaluates over the filter context defined by the visual and model. A further measure can use CALCULATE to modify that context for a specific business rule, such as approved transactions. The formula is only valid when Status values and the underlying rows already represent the intended commercial events.
Calculated columns store row-level results in the model under many storage configurations, while measures calculate as queries are evaluated. Prefer a measure when the desired result depends on filters selected by a report consumer. Use a column when a stable row attribute is genuinely required for grouping, sorting or a relationship, after considering where the transformation should ideally happen.
For a delivery-rate measure, decide whether the denominator is all orders, orders promised during the period or parcels eligible for delivery. The same DAX function can compute different percentages depending on that definition. A zero denominator should be handled intentionally, and incomplete deliveries must not vanish because of an inner join that excludes them.
For deeper syntax, DAX measures and filter context are a separate topic. The modeling obligation is to make the calculation’s business scope, relationships and date logic clear enough that an independent reviewer can test the answer.
Choose storage mode and performance strategy with evidence
Import loads data into a semantic model and often provides fast query performance when the model fits the refresh and capacity constraints. DirectQuery sends appropriate queries to a connected source, making source performance and latency important. Direct Lake is an option for supported Fabric scenarios and has its own capacity and fallback considerations. These approaches are not interchangeable defaults.
Use a representative dataset and known queries before selecting a mode. A model with unnecessary high-cardinality columns, ambiguous relationships and complex measures can be slow under any storage mode. Remove unused detail if it is not needed; when history must remain, consider suitable aggregations or incremental-refresh design rather than deleting evidence purely to accelerate a demo.
Inspect performance through Power BI’s available visual and DAX diagnostic tools. A slow report might be waiting on a remote database, evaluating an expensive measure or rendering a needlessly detailed visual. Without separating those causes, a blanket switch from DirectQuery to Import may exchange one problem for new refresh or governance constraints.
Verify row-level security separately from report design
Row-level security (RLS) restricts what data a permitted user can see within a semantic model according to defined roles and filters. A report page filter is not a security boundary. Create roles from actual business entitlements, test representative users and confirm that relationship paths do not expose unexpected records.
Power BI’s workspace permissions require care: RLS restricts Viewer users and does not apply to workspace Admin, Member or Contributor roles in the same way. A user granted a higher workspace role may bypass an intended row restriction. Model security and workspace access therefore need to be reviewed together. When combining source groups in composite models, check the separate rules governing remote and local security instead of assuming one global filter automatically secures everything.
The Power BI workspace discussion provides broader publishing context; the model owner must still test permissions at the identity level. An attractive report preview under the author’s own account tells little about what a least-privileged viewer sees.
Reconcile measures before building the final report
Choose three independent calculations from the source systems: total confirmed sales, distinct fulfilled orders and open orders awaiting dispatch. Compare them by selected dates and product categories against source queries or audited extracts. Drill into discrepancies until the cause is known. Differences may come from grain, row filtering, currency conversion, duplicated keys, late-arriving events or relationship direction.
A clear model should let an analyst change from monthly to regional analysis without rewriting the meaning of those measures. It should also support a practical explanation when a filter excludes a row. This is a stronger quality test than the number of visual types the model can feed.
The current PL-300 model concepts are useful context because Microsoft’s 2026 objectives include preparing data, relationships, calculations, performance and security. This article’s narrower purpose is to create a semantically correct and testable model. Once that foundation is reliable, reporting can become expressive without manufacturing its own arithmetic.