Power BI interview questions test three layers: tool mechanics (Power Query, data modeling, DAX), analytical reasoning (how you'd solve a specific reporting problem), and judgment (when to use a measure vs. a calculated column, or Import vs. DirectQuery). The strongest candidates demonstrate they can build and troubleshoot a full model end-to-end, not just recite DAX syntax. This guide covers the questions actually asked at each level, with the reasoning behind good answers.
Power BI interviews usually test three things at once: whether you actually understand data modeling and DAX (not just dragging fields onto a canvas), whether you can build something performant and maintainable, and whether you've dealt with the real-world mess of gateways, refreshes, and stakeholders who want 47 KPIs on one page. Use this page to check you can explain the 'why' behind your choices, not just the 'how' — that's what separates people who've built a few dashboards from people who own BI in production.
This is the warm-up round where interviewers check you understand the moving pieces — Desktop vs Service vs Report Server, how a .pbix file is structured, and where Power BI sits relative to other BI tools. They're also probing whether you understand the import vs DirectQuery vs live connection distinction because that decision affects everything downstream. Weak candidates describe features; strong candidates describe trade-offs.
Interview tip — Be ready to draw the architecture on a whiteboard in 30 seconds — Desktop, gateway, Service, workspace, dataset — and explain data flow between them.
It's basically a zip file with a few things bundled together — the data model with any imported data, the Power Query transformation logic, the DAX measures, and the report layout with all the visuals. When you open it in Desktop it just unpacks that into the three panes you're used to.
Import loads a compressed copy of the data into Power BI's own engine, so it's fast and you get full DAX, but it's only as fresh as your last refresh. DirectQuery sends queries live to the source every time you interact with a visual, so it's always current but performance depends entirely on the source database. Live Connection is specifically for connecting to an existing Analysis Services or Power BI dataset — you're not building your own model, you're just building reports on top of someone else's.
When the data's too huge to realistically import, when you need near real-time numbers like a live ops dashboard, or when there's a compliance reason the data can't leave the source system. Otherwise I default to Import because the performance and DAX flexibility are so much better.
It's mixing Import and DirectQuery tables in the same model — say your transaction table is DirectQuery because it's huge, but your date and product dimensions are Import for speed. Power BI handles the relationships across the two modes automatically, though you do need to watch out for performance issues on the DirectQuery side.
Power BI's DAX and data modeling engine is more powerful for building an actual semantic layer, and it's dirt cheap if you're already on Microsoft 365 or Azure. Tableau's traditionally been stronger on pure visual polish and exploratory analysis, though Power BI's closed that gap a lot in recent years. In practice the choice usually comes down to what's already in the org's tech stack, not raw feature comparison.
This is the heart of most technical interviews — star schema versus snowflake, fact and dimension tables, relationship cardinality, and why a flat wide table is usually a trap. Interviewers want to see you can look at messy source data and design a model that's both fast and understandable to a business user. They'll often give you a scenario and ask you to sketch the model out loud.
Interview tip — Practice explaining star schema in plain English with a concrete example — sales fact, date/product/customer dimensions — because you'll almost certainly be asked to design one live.
A flat table looks simple but it duplicates dimension data across every row, bloats the model size, and makes DAX filtering way harder because everything's mixed together. With a star schema — one fact table surrounded by clean dimension tables — filters propagate properly, the model compresses way better, and it's actually easier for a business user to understand what a 'customer' or 'date' means.
Fact table holds the numbers you're measuring — sales amount, quantity, whatever — and it's usually long and narrow with lots of rows. Dimension tables hold the descriptive attributes you slice by, like customer name, product category, or date, and they're what you actually put on rows, columns, and filters in your visuals.
First I try to avoid it by adding a bridge table between the two entities — that turns it into two one-to-many relationships, which is cleaner and performs better. If I can't avoid it, Power BI does support native many-to-many relationships now, but I'm careful about it because filter propagation can get unpredictable and slow.
Snowflake normalizes dimensions further, so like your product dimension splits into product, subcategory, and category tables linked together. I generally avoid it in Power BI because it adds relationship hops that slow down DAX and confuse business users — I'd rather denormalize back into one flat product dimension unless there's a really good reason not to.
That's when one dimension, usually date, needs to relate to a fact table in more than one way — like order date and ship date both pointing to the same calendar table. Power BI only lets one relationship be active at a time, so I either create separate physical date tables for each role or use USERELATIONSHIP in DAX to activate the inactive one when I need it.
Cardinality should reflect reality — usually one-to-many from dimension to fact — and I keep cross-filter direction single wherever I can because bidirectional filtering can cause ambiguous filter paths and tank performance. I only turn on bidirectional when I've got a specific need, like a many-to-many bridge table, and even then I test it carefully.
For type 1, where you just overwrite old values, it's simple — the refresh just updates the dimension table. For type 2, where you need history, I handle that upstream in the source or the ETL layer with effective-dated rows and a surrogate key, because Power BI itself isn't really built to manage historical versioning inside the model.
Not sure which path fits? Get a free 1:1 consultation with our team.
Here they're checking whether you can actually clean and shape messy data before it hits the model, not just rely on someone handing you a perfect table. Expect questions on query folding, merge vs append, and handling things like unpivoting or parameterizing sources. They also probe whether you understand performance implications of what you're doing in the Query Editor.
Interview tip — Know query folding cold — it's the single most common thing that trips people up in interviews and in real projects.
Query folding is when Power Query pushes your transformation steps back down to the source system as native SQL instead of pulling everything into memory first and doing the work there. It matters hugely for performance — if folding breaks partway through your steps, everything after that point runs locally and slowly, so I always check the 'view native query' option to make sure my early steps are still folding.
Things like adding a custom column with certain M functions, merging queries from two different data sources, or using Table.Buffer will usually stop folding. My rule of thumb is to do all the filtering and column selection first while it can still fold, and push the fancier logic to the end or handle it upstream if possible.
Append is for stacking rows on top of each other, like combining twelve months of files with the same columns. Merge is Power Query's version of a join — you're pulling columns from a second table based on a matching key, like joining a lookup table onto your fact table.
I'd point Power Query at the folder using the 'Folder' connector, then use the combine files feature, which builds a function that applies the same transformation to every file automatically. That way if a 51st file shows up next month, I just refresh and it picks it up without me touching the query.
A parameter is a reusable value — like an environment name or a date cutoff — that you can plug into multiple queries so you're not hardcoding the same string everywhere. It makes moving between dev and prod, or changing a filter date, a one-place edit instead of hunting through every query.
Select the columns that need to become rows, right-click, and choose unpivot columns — Power Query turns each of those column headers into an attribute value and stacks the data long-ways. It's the classic fix for spreadsheets where someone's put months across the top as separate columns instead of as row values.
First thing I check is whether folding is actually happening for as many steps as possible. After that I look at whether I'm pulling more columns or rows than I actually need, whether merges are happening on indexed keys, and whether I can push heavy joins back to the source database instead of doing them in the M engine.
This is where interviews separate people who can write measures from people who just copy-paste from the internet. Expect them to test calculated column vs measure, aggregation functions, and basic filter functions like CALCULATE. They're listening for whether you understand row context versus filter context, even at a basic level, because everything else in DAX builds on that.
Interview tip — Be able to explain the difference between a calculated column and a measure without hesitating — it's asked in almost every single Power BI interview.
A calculated column gets computed row by row when you refresh the data and it physically sits in the table taking up storage, so it's good for things you want to slice or filter by. A measure is computed on the fly at query time based on whatever's in the current filter context, it doesn't take up storage, and it's what you use for pretty much all your actual numbers like totals and ratios.
CALCULATE changes the filter context that an expression is evaluated in — you give it an expression and then one or more filter arguments, and it recomputes that expression as if those filters were applied. It's basically the one function that lets you override or add to whatever filters are already coming from the visual, and almost every non-trivial DAX measure has a CALCULATE in it somewhere.
Row context is what exists when you're iterating row by row, like inside a calculated column or a function like SUMX, where DAX knows which specific row it's currently on. Filter context is the set of filters applied from slicers, visual axes, or CALCULATE, that narrows down which rows get included when a measure is evaluated. The classic gotcha is that row context doesn't automatically become filter context — that's what the CALCULATE-triggered context transition is for.
SUM just adds up a single column directly. SUMX iterates row by row over a table and evaluates an expression for each row before summing the results, so you use it when you need to multiply or combine columns first — like quantity times price — before adding it all up.
ALL removes filters from a table or column, so if you wrap a column in ALL inside a CALCULATE, you're ignoring whatever the user selected in a slicer for that column. I use it a lot for things like percent-of-total calculations, where I need the grand total to stay fixed regardless of what's filtered on the visual.
COUNT only counts numeric values in a column, COUNTA counts anything non-blank including text, and DISTINCTCOUNT gives you the count of unique values. I get asked to use DISTINCTCOUNT constantly for things like unique customers or unique orders.
VAR lets you store an intermediate calculation with a name so you're not repeating the same expression multiple times in a measure. It makes the code more readable, but it also genuinely improves performance because DAX only evaluates that expression once instead of recalculating it every time it's referenced.
This is where they push harder — time intelligence functions, context transition, iterator functions, and handling things like ranking or running totals. They'll often give you a real business scenario, like year-over-year growth or a cumulative total, and want you to reason through it out loud rather than recite syntax. Confidence explaining why something like context transition happens matters more than perfect syntax.
Interview tip — Practice explaining context transition with a concrete example — it's the concept that trips up even experienced people, so nailing it out loud is a real differentiator.
I'd write a measure using SAMEPERIODLASTYEAR or DATEADD wrapped in CALCULATE to get the prior year's value against a proper marked date table, then subtract that from the current measure and divide by the prior year value to get a percentage. The key requirement people forget is you need a continuous, marked date table for time intelligence functions to work correctly at all.
It's what happens when a row context gets converted into an equivalent filter context, and it happens automatically anytime you call CALCULATE — or any measure, since measures are implicitly wrapped in CALCULATE. So if you're inside a SUMX iterating row by row and you reference a measure, that measure suddenly sees a filter context as if you'd filtered down to just that one row, which is why totals and calculated columns can behave really differently than you'd expect.
Typical approach is CALCULATE of your sales measure, wrapped with a FILTER over ALL of the date table where date is less than or equal to the max date in the current context. That effectively re-expands the filter to include everything up to today for each row, giving you the cumulative effect.
I'd use RANKX, passing it a table like ALL products filtered to the same category, the current sales measure, and specifying descending order. The trick is getting the filter argument right so the ranking resets per category instead of ranking globally across everything.
CALCULATE's own filter arguments are simple boolean conditions on a column and they're generally faster because the engine can optimize them directly. FILTER returns an actual table after scanning row by row, which is more flexible for complex conditions but usually slower, so I only reach for FILTER when a simple CALCULATE condition can't express what I need.
I use CALCULATE with REMOVEFILTERS or ALL just on that specific column, not the whole table, so everything else the user's filtered stays intact. That's the pattern for things like showing a category's percent of the overall total while still respecting a date slicer.
This tests taste and judgment as much as technical skill — can you pick the right visual for the question being asked, avoid clutter, and design something an executive will actually use instead of ignore. Interviewers probe your thinking on things like when to use a table versus a chart, how you handle too many KPIs on one page, and accessibility or color choices. They're also checking you understand bookmarks, drill-through, and tooltips as real functional tools, not gimmicks.
Interview tip — Have one real example ready where you pushed back on a stakeholder's request for a busy dashboard and simplified it — this question comes up almost every time.
I start with the question the user's actually trying to answer, not the data itself — trend over time is a line chart, comparing categories is a bar chart, part-to-whole is usually a stacked bar rather than a pie because pies are hard to read accurately past three or four slices. If someone just needs exact numbers to scan, honestly a well-formatted table beats a fancy chart every time.
I'd push back gently by asking what decision they're trying to make with each number, because usually half of them are 'nice to know' rather than actionable. I'd propose a top summary page with the five or six things that actually drive decisions, and put the rest behind drill-through or a detail page so the main view stays usable.
Drill-down moves through a hierarchy within the same visual, like going from year to quarter to month on the same chart. Drill-through takes you to an entirely different page, usually a detail page, filtered to whatever you right-clicked on in the source visual.
Bookmarks capture the state of a page — which filters are applied, which visuals are visible, even the current zoom — so you can jump between saved states with a button. I've used them to build a toggle between a 'summary view' and 'detail view' on the same page without needing two separate pages.
I avoid relying on red-green as the only signal and add a second cue like an icon, pattern, or explicit label, and I use Power BI's built-in accessible color palettes instead of just default theme colors. I also make sure tab order and alt text are set up properly for screen readers if it's going to a wider audience.
Fewer visuals per page, avoid unnecessary custom visuals that are slower than native ones, and turn off things like default 'apply all slicers' interactions if they're not needed. I also try to limit the number of visuals hitting the model simultaneously on load — a page with 15 visuals all firing separate DAX queries on open is going to feel sluggish no matter how good the model is.
This is where senior candidates get separated from junior ones — can you actually diagnose why a report is slow using Performance Analyzer or DAX Studio, and do you understand VertiPaq storage well enough to reduce model size. Interviewers want a real story: what was slow, how did you find the bottleneck, what did you change. Generic answers like 'I optimized the DAX' without specifics are an instant red flag.
Interview tip — Have one concrete before/after performance story memorized with actual numbers — 'load time went from 15 seconds to 3' lands way better than vague claims.
First stop is Performance Analyzer inside Desktop — it breaks down each visual's load time into the DAX query, visual rendering, and 'other,' so I can immediately see if it's a query problem or a rendering problem. If it's the DAX query that's slow, I pull it into DAX Studio to see the actual query plan and check whether it's spending time in the storage engine or the formula engine.
Storage engine time is the fast, highly parallelized part where VertiPaq is just scanning compressed data, and formula engine time is the slower, single-threaded part doing row-by-row logic that the storage engine couldn't handle on its own. If a query's spending most of its time in the formula engine, that's usually a sign the DAX itself needs rewriting to push more work down to the storage engine.
Remove columns you don't actually use, especially high-cardinality ones like unique IDs or full timestamps you don't need at that granularity, since VertiPaq compresses low-cardinality columns way better. I also switch numeric-looking text columns to actual number types, disable auto date/time tables I'm not using, and aggregate data to a coarser grain in Power Query if the report doesn't need row-level detail.
Usually it's iterating over huge tables unnecessarily, using FILTER when a simple CALCULATE condition would do, nested iterators like SUMX inside SUMX, or too many context transitions from calling one measure inside another repeatedly. Variables help a lot because they stop DAX from re-evaluating the same expensive expression multiple times.
Aggregation tables are pre-summarized versions of your big fact table, like daily totals instead of row-level transactions, that Power BI can automatically redirect queries to when the visual doesn't need row-level detail. It's a big performance win on massive DirectQuery or huge Import models where most user queries are actually asking for summary-level numbers anyway.
I'd check the refresh history error message first since it usually points at either a gateway connectivity issue, a credential that expired, or a data source schema change that broke a query. If it's intermittent, I look at whether it's a timeout on a big query and consider incremental refresh instead of pulling the whole table every time.
Security questions test whether you understand how to restrict data per user without maintaining twenty copies of the same report. Expect questions on static versus dynamic RLS, how it interacts with roles, and edge cases like what happens with multiple roles assigned to one user. They may also branch into broader governance — sensitivity labels, workspace access, and dataset certification.
Interview tip — Practice explaining dynamic RLS using USERPRINCIPALNAME with a concrete manager-hierarchy example — it's the most commonly asked security scenario.
RLS restricts which rows a user sees based on their identity, and you implement it by creating roles in Power BI Desktop with a DAX filter expression on a table, then assigning users or groups to those roles in the Service. So a 'West Region' role might just filter the region column to 'West' and any user assigned there only ever sees West region data.
Static RLS is where you hardcode the filter value into the role, like literally typing Region equals 'West,' so you need a separate role for every region. Dynamic RLS uses a function like USERPRINCIPALNAME to compare the logged-in user's email against a table in your model, so one single role and one DAX expression can serve every user differently based on who's logged in.
I'd build an employee table with a manager hierarchy, then use PATH and PATHCONTAINS functions in the RLS filter so a manager's login matches not just their own row but anyone underneath them in the org chart. That way one dynamic role handles every level of the hierarchy without needing separate roles per manager.
Power BI unions the results — the user sees rows that satisfy either role's filter, not the intersection. That's an important gotcha because people sometimes assume it's an AND when it's actually an OR.
The RLS setup itself works the same in Desktop, but with DirectQuery the filter gets pushed down and applied at the source query level, so performance depends on how well the source can handle that filtered query. With Import it's applied within Power BI's own engine against the compressed in-memory data, which is generally faster.
In Desktop I use 'View as' under the Modeling tab to simulate a specific role or even a specific username, which lets me confirm the filters actually work before it ever goes to the Service. I always test it as a few different users, not just the role in the abstract, because edge cases in the hierarchy logic show up fast.
This covers the operational side — workspaces, apps, deployment pipelines, gateways, and how refreshes actually get scheduled and monitored in production. Interviewers are checking if you've actually operated Power BI at scale, not just built reports in isolation, so they'll ask about licensing tiers, dataset ownership, and how you handle a multi-environment dev-to-prod process. This is especially heavily probed for anyone claiming admin or lead-level experience.
Interview tip — Be ready to walk through your actual dev-to-test-to-prod promotion process end to end, including who approves what — vague answers here read as 'I've never worked on a real team.'
A workspace is the collaborative backend area where you and your team build and edit reports and datasets together. An app is the polished, read-only front-end you publish from that workspace for actual end users to consume, so you can control exactly what they see without giving them edit access or workspace clutter.
Deployment pipelines give you dev, test, and production stages within the Service so you can promote a report through environments in a controlled way instead of manually republishing files. It also lets you swap data sources per stage, so dev points at a test database while prod points at the real one, without changing the report itself.
A gateway is a piece of software installed on-premises that lets the Power BI Service securely reach data sources that aren't exposed to the internet, like an on-prem SQL Server. You need it for both scheduled refresh and DirectQuery against on-prem sources, and there's a personal mode for individual use versus an enterprise mode for shared, managed connections across a team.
You define a policy with a rolling window, like refresh the last 5 days but keep 3 years of history, and Power BI only pulls and processes the new or changed partitions instead of reloading the entire table every time. It massively cuts refresh time and load on the source system for large fact tables, and it requires query folding to actually work well.
Pro is per-user and requires everyone viewing a report to also have a Pro license unless it's in a Premium capacity. Premium is capacity-based, so once content sits in a Premium workspace, anyone in the org can view it without their own individual license, plus you get bigger model size limits and more frequent refreshes. Premium Per User gives Premium-like features but licensed per person instead of buying a whole capacity, which suits smaller orgs that still want the extra features.
I push for a shared dataset approach — build one certified, well-governed dataset and let multiple reports connect to it live instead of everyone building their own copy of the same model. It cuts down on maintenance and inconsistent numbers across reports, and certification or endorsement in the Service signals to the team which dataset is the trustworthy source.
This is where interviewers stop asking definitions and start testing judgment — messy requirements, conflicting numbers, or a report that broke in production. They want to hear your actual diagnostic process and how you communicate with non-technical stakeholders when something goes wrong. This is often where behavioral and technical blend together.
Interview tip — Bring two or three specific war stories from real projects — a broken refresh, a stakeholder disagreement over numbers, a performance fire drill — and practice telling them in under a minute each.
First I go check the obvious stuff — is the report using a stale cached data set, is there a filter context difference, or is the source system itself showing a different snapshot in time. I'll trace one specific number all the way back through the DAX, the model relationships, and the Power Query steps until I find exactly where it diverges, then explain that in plain terms to the stakeholder instead of just saying 'trust me, it's right.'
I get both of them in a room, or at least on the same email thread, and ask each what decision they're trying to make with the number, because usually the conflict is actually about two different definitions of the same word, like 'revenue' meaning gross to one person and net to another. Once we agree on a single definition and I document it clearly, I build both if truly needed as clearly labeled separate measures rather than silently picking one.
I had a sales dashboard with a huge transaction-level fact table on Import mode, and load time was around 15 seconds per page, which people were complaining about. I ran Performance Analyzer, found a couple of measures using FILTER unnecessarily and a bidirectional relationship causing ambiguous filter paths, fixed the DAX, switched that relationship to single direction, and got it down to about 3 seconds.
I'm upfront about the limitation instead of forcing an ugly workaround that'll be a maintenance nightmare later, and I offer the closest realistic alternative — sometimes that's a custom visual, sometimes it's restructuring the ask itself. I'd rather have that honest conversation early than deliver something fragile that breaks the next time the data changes.
I start by getting a handful of real example questions the stakeholders want answered, not abstract requirements, because that tells me what the model actually needs to support. I'll usually build a rough prototype fast with a subset of data, show it to them within a week, and let that conversation sharpen the real requirements instead of trying to nail everything upfront on paper.
I push everything into a shared, certified dataset with the core measures already built in and documented, so people are reusing the same 'Total Revenue' instead of everyone writing their own slightly different version. I also keep a simple data dictionary alongside it so there's no ambiguity about what a measure actually means.
Serious about landing the role? Structured, instructor-led practice with real projects makes the difference — see Power BI Training.
Understanding the concept is the start. Being able to apply it is a separate skill, and it follows a fairly consistent path — this is the arc a structured programme takes you through.
*{position:relative;z-index:1} .ci-header{display:flex;align-items:flex-start;justify-cont · Introduction to Power BI & Environment Setup · Connecting to Data Sources · Data Transformation with Power Query · Data Modeling · DAX Fundamentals · Advanced DAX · Building Reports and Visualizations
Want a structured, instructor-led path through all of this — with hands-on projects and real feedback? → Power BI Training
Browse our upcoming batches — live, instructor-led, delivered on Orbit.