Power BI Bi-Directional Relationships - When to Use Them and When to Avoid Them
If I had to pick one Power BI modelling concept that causes the most unnecessary headaches, bi-directional relationships would be right up there. They sound useful. They're easy to enable - just a checkbox. And they solve real problems in certain situations. But they also have a habit of quietly degrading model performance and confusing report users in ways that take ages to diagnose.
We've worked on dozens of Power BI models for Australian organisations across finance, logistics, and retail. The pattern repeats itself: someone enables bi-directional filtering to fix one slicer issue, then another, and before you know it the model has eight bi-directional relationships and report load times have tripled. Nobody connects the dots until the performance complaints stack up.
Microsoft has published thorough guidance on bi-directional relationships that covers the technical specifics. But here's what we've learned about applying that guidance in practice.
What Bi-Directional Filtering Actually Does
In a standard Power BI relationship, filters flow in one direction - typically from the dimension table (the "one" side) to the fact table (the "many" side). If you have a Customer table related to a Sales table, selecting a customer filters the sales. That's the expected behaviour and it covers most reporting scenarios.
A bi-directional relationship lets filters flow both ways. So now the Sales table can also filter the Customer table. This sounds harmless, but it fundamentally changes how the model resolves queries. Every visual on every page needs to evaluate filters in both directions, and that processing cost adds up.
The Three Scenarios Where Bi-Directional Actually Makes Sense
Not all bi-directional relationships are bad. There are three specific situations where they're either required or genuinely useful.
One-to-One Relationships
Every one-to-one relationship in Power BI is automatically bi-directional. You can't change this, and you shouldn't try to work around it. If you have two tables with a one-to-one relationship, Power BI needs to filter in both directions to keep things consistent.
That said, most one-to-one relationships in models I've reviewed shouldn't exist in the first place. They usually indicate that someone split a table into two when there was no good reason to. If both tables have the same grain - one row per customer, say - just merge them. Fewer tables means fewer relationships, which means better performance and simpler maintenance.
Many-to-Many Through a Bridge Table
This is the legitimate use case that comes up most often. You have two dimension tables - maybe Product and Supplier - and a single product can have multiple suppliers while a single supplier provides multiple products. To model this, you need a bridge table (sometimes called a factless fact table) sitting between them.
For filters to propagate from one dimension through the bridge to the other dimension, at least one relationship needs to be bi-directional. There's no way around this if you need cross-filtering between those dimensions.
We worked with a procurement team that needed to see which suppliers provided products in a specific category, and which categories a specific supplier covered. The bridge table pattern with bi-directional filtering was the right answer. But we were careful to keep it contained - only the relationships touching the bridge table were set to bi-directional. Everything else stayed single-direction.
Dimension-to-Dimension Analysis
Sometimes you want to analyse one dimension through the lens of another, using a fact table as the bridge. Questions like "How many product colours were sold to Australian customers?" or "How many regions purchased jeans?" require filters to propagate from one dimension, through the fact table, to another dimension.
This works by treating the fact table as a bridge table. But - and this is the important bit - there's usually a better way to do it.
The Better Alternative - CROSSFILTER in DAX
For dimension-to-dimension analysis, we almost always recommend using the CROSSFILTER DAX function instead of setting the relationship to bi-directional at the model level. Here's why: a model-level bi-directional relationship affects every single query against that relationship. CROSSFILTER only activates bi-directional filtering for the specific measure that needs it.
The difference matters. Consider this measure:
Different Countries Sold =
CALCULATE(
DISTINCTCOUNT(Customer[Country-Region]),
CROSSFILTER(
Customer[CustomerCode],
Sales[CustomerCode],
BOTH
)
)
This measure temporarily enables bi-directional filtering between Customer and Sales during its evaluation. Every other measure continues to use single-direction filtering. Your model stays performant for 95% of its workload, and you only pay the bi-directional cost for the specific calculation that needs it.
We've seen models where switching from model-level bi-directional relationships to measure-level CROSSFILTER cut report load times by 40-60%. That's not a marginal improvement. On larger datasets - anything north of a few million rows - the difference becomes dramatic.
The Slicer Problem - "Show Items With Data"
This is the scenario that most often leads people to enable bi-directional filtering when they shouldn't. You have a report page with two slicers - say Country and Product. A user selects "Australia" in the Country slicer, and they want the Product slicer to only show products that were actually sold in Australia.
That's a reasonable request. And bi-directional filtering between Product and Sales achieves it. When the Country slicer filters the Sales table, the bi-directional relationship then filters the Product table to show only products with matching sales.
The problem is that this is the expensive way to solve it. Every visual on the page now deals with bi-directional filtering, not just the slicer.
There's a much cheaper approach. Keep the relationship single-direction, and apply a visual-level filter to the Product slicer instead. Create a measure like:
Total Quantity = SUM(Sales[Quantity])
Then filter the Product slicer to only show items where Total Quantity "is not blank." You get the exact same user experience - the slicer dynamically shows only relevant products - without the performance penalty of bi-directional filtering. The visual-level filter approach is local to that one slicer rather than affecting the entire model.
I'll be honest, the visual-level filter approach is slightly more setup work. You need to create the measure and configure the filter. But it takes maybe three minutes, and the performance benefit is permanent.
Warning Signs Your Model Has Too Many Bi-Directional Relationships
After auditing countless Power BI models, here are the red flags we look for:
Report pages take more than 10 seconds to render. There are many possible causes, but bi-directional relationships are one of the first things to check. Open Performance Analyzer (under the View tab) and look at which visuals are slow. If slicers are among the slowest visuals, bi-directional filtering is a likely culprit.
Slicers show unexpected items or items disappear unpredictably. Bi-directional filtering can create complex filter chains where one slicer affects another in ways you didn't intend. A product slicer might show different options depending on whether the user selected a date range first or a customer segment first. This inconsistency confuses users.
Circular dependency errors. If Power BI tells you it detected a circular dependency in your model, you've created a loop of bi-directional relationships. This is a clear signal to rethink your model structure.
More than two or three bi-directional relationships in the model. This isn't a hard rule, but when I see a model with five or more bi-directional relationships, there's almost certainly at least a couple that could be replaced with CROSSFILTER or visual-level filters.
Our Recommended Approach
When we build or refactor Power BI models at Team 400, we follow a simple principle: start with all single-direction relationships, then add bi-directional only where there's no reasonable alternative.
In practice, this means:
- Set up your star schema with all single-direction relationships
- For many-to-many bridge tables, enable bi-directional on the bridge relationships only
- For "show items with data" slicer behaviour, use visual-level filters with a measure
- For dimension-to-dimension analysis, use CROSSFILTER in the specific measures that need it
- Only enable model-level bi-directional as a last resort
This approach keeps the model fast and predictable. It's easier to troubleshoot because the filter flow is explicit and documented. And when you do use bi-directional filtering through CROSSFILTER, it's right there in the measure definition where anyone can see it.
Getting the Model Right From the Start
The best time to think about relationship direction is during initial model design, not after users start complaining about slow reports. If you're building a new model or migrating to Power BI, spend time on your star schema before you build a single visual. Get the grain of your fact tables right. Make sure your dimension tables are complete. Define how filters should flow.
If you need help getting your Power BI model structure right, our data and analytics consulting team works with organisations across Australia on exactly this kind of work. We also run through these concepts in our AI and analytics training sessions if you want your team to build this knowledge internally.
Bi-directional relationships are a useful tool in the right context. They're just not the default answer to every filtering question. Use them sparingly, prefer CROSSFILTER for targeted scenarios, and your models will be faster and easier to maintain for it.