Excelgoodies logo +1 650 491 3131

LEARN THIS HANDS ON

Power BI Reporting

ET . Live Online FILLING FAST
View all upcoming batches
Power BI for Insurance & Healthcare Teams: Building Claims, Utilization and Risk Dashboards that Actually Hold Up

Power BI for Insurance & Healthcare Teams: Building Claims, Utilization and Risk Dashboards that Actually Hold Up

Claims, utilization and risk data in insurance and healthcare is usually scattered across adjudication systems, data warehouses and vendor feeds, with different grain, different IDs and different refresh cadences. You get asked for a single view of loss ratios, care gaps and high‑cost members, and your existing Power BI reports either time out, misstate metrics, or collapse under new benefit years.

This article walks through a concrete scenario of building Power BI for Insurance & Healthcare Teams: Claims, Utilization and Risk Dashboards, focusing on how to structure the model, handle large fact tables, and design measures that actuaries, clinicians and finance will trust. The examples assume an employer‑sponsored environment in a market like Chicago, where multiple teams share Fabric and Power BI but have different analytical needs.

Scenario: One Shared Model, Three Very Different Audiences

Imagine an internal analytics group supporting:

  • A claims operations team (adjusters and managers)
  • A healthcare utilization management team (nurses, medical directors)
  • A risk/actuarial team (pricing, reserving, population health)

Data sources:

  • Claims fact table (~50M rows per recent year, multiple years kept online)
  • Eligibility/enrollment table (member-month grain)
  • Provider master (NPI, specialty, facility vs professional)
  • Risk scores table (episode or member-level, from a vendor feed)
  • Reference tables (benefit plan, product line, region, diagnosis group)

Technical constraints:

  • Power BI Premium capacity (Fabric) shared across departments
  • Mixed storage modes: some DirectQuery into a warehouse, some Import
  • Refresh window overnight, limited DBA support

Pain points today:

  • Claims dashboards are slow or hit query timeouts
  • Utilization views double-count members or visits when slicing by month
  • Risk dashboards show different populations than finance’s loss ratio report

We’ll rebuild this into a single semantic model that can serve multiple dashboards without breaking under load.

Step 1: Choose Storage Modes Per Fact Table

The first decision that affects everything else is storage mode. For this scenario, assume you have:

  • A claims warehouse in SQL or Fabric Lakehouse
  • Smaller dimension tables (providers, plans, regions) that change relatively slowly

A pragmatic split that often works:

  • Claims: DirectQuery or Composite (depending on volume and SLA)
  • Eligibility, Risk Scores, Reference Dimensions: Import

Key points to keep straight:

  1. Import mode

    • Data is cached in the dataset in Power BI.
    • Query performance is typically faster and more predictable than DirectQuery because it uses the VertiPaq engine.
    • Subject to dataset size limits and memory constraints in your Premium capacity.
  2. DirectQuery mode

    • Queries are sent to the underlying data source (e.g., SQL database) at run time.
    • Row-level security and data freshness are aligned with the source, but performance depends heavily on source indexing and query design.
    • Many modeling features work, but some operations (especially complex calculated tables depending on DirectQuery sources) are limited or not supported.
  3. Composite models

    • Allow Import and DirectQuery tables in the same dataset.
    • Relationship behavior is mostly consistent with Import, but performance can vary depending on how many DirectQuery tables are involved in a query.

For a large claims fact table, a common pattern is:

  • Use DirectQuery for the current and previous benefit year, where adjusters and utilization teams need near-real-time data.
  • Use Import for older years aggregated to a higher grain (e.g., claim-month or member-year), where actuaries need history but not daily updates.

This split is best implemented in the warehouse or Lakehouse first (separate objects for detailed vs aggregated claims) and then surfaced into Power BI as separate tables, to avoid complex calculated tables over DirectQuery sources.

Step 2: Model Grain and Relationships Carefully

The core modeling risk in insurance and healthcare dashboards is mismatched grain:

  • Claims at claim-line or header level
  • Eligibility at member-month
  • Risk scores at member-year or episode

The semantic model needs to make these relationships explicit.

  • DimDate (Import): one row per date, with flags for month, quarter, benefit year
  • DimMember (Import): one row per member ID
  • FactEligibility (Import): one row per member per month (member-month)
  • FactClaims_Current (DirectQuery): one row per claim line
  • FactClaims_History (Import): one row per member per month or per claim (depending on volume)
  • FactRiskScores (Import): one row per member per risk period (e.g., member-year)
  • DimProvider, DimPlan, DimRegion, DimDiagnosisGroup (Import): standard dimensions

Relationship rules that usually keep you out of trouble:

  1. One active relationship per pair of tables at a time.

    • Example: DimDate → FactClaims_Current on ClaimServiceDate as the active relationship.
    • If you also need relationships on ClaimPaidDate, use inactive relationships and USERELATIONSHIP in measures.
  2. Eligibility as the core population table.

    • DimMember → FactEligibility: one-to-many, active.
    • FactClaims_Current and FactRiskScores also relate to DimMember, but population counts come from eligibility.
  3. Avoid many-to-many where possible.

    • For diagnosis groups, create a bridge table if a claim can have multiple diagnosis groups, and model it explicitly.

Example: handling service vs paid date

Suppose you need both incurred (service date) and paid views of claims. Create two relationships from DimDate to FactClaims_Current:

  • Active: DimDate[Date] → FactClaims_Current[ServiceDate]
  • Inactive: DimDate[Date] → FactClaims_Current[PaidDate]

Then define measures like:

Total Paid Amount by Paid Date :=
CALCULATE(
    SUM(FactClaims_Current[PaidAmount]),
    USERELATIONSHIP(DimDate[Date], FactClaims_Current[PaidDate])
)

Total Incurred Amount by Service Date := SUM(FactClaims_Current[AllowedAmount])

This keeps the model clean while letting different teams switch date semantics explicitly in their visuals.

Step 3: Design Measures for Claims, Utilization and Risk

You’ll typically need three families of measures:

  1. Claims performance (loss ratio, paid vs allowed, open vs closed)
  2. Utilization (admissions per 1,000, ED visits per 1,000, readmission rates)
  3. Risk and population health (average risk score, high-risk member counts)

Claims measures

Start with core measures that are unambiguous:

Total Claims Paid :=
SUM(FactClaims_Current[PaidAmount]) +
SUM(FactClaims_History[PaidAmount])

Total Claims Allowed := SUM(FactClaims_Current[AllowedAmount]) + SUM(FactClaims_History[AllowedAmount])

Total Premium := SUM(FactEligibility[PremiumAmount])

Loss Ratio := DIVIDE([Total Claims Paid], [Total Premium])

Notes:

  • The combined measures over Current + History assume the same currency and benefit year definitions; if that’s not true, separate measures by product line or year.
  • Using DIVIDE avoids errors on zero premium segments.

Utilization measures

Utilization is usually per 1,000 members, using eligibility as the denominator.

Member Months :=
SUM(FactEligibility[MemberMonths])

Admissions := CALCULATE( COUNTROWS(FactClaims_Current), KEEPFILTERS(FactClaims_Current[PlaceOfService] = "Inpatient"), KEEPFILTERS(FactClaims_Current[ClaimType] = "Facility") )

Admissions per 1000 := VAR denom := [Member Months] RETURN IF( denom > 0, ( [Admissions] / denom ) * 1000, BLANK() )

Key points:

  • The filter conditions in Admissions should align with your internal definition (place of service, revenue codes, etc.). Keep those filters centralized in measures rather than repeated in visuals.
  • Use eligibility as denominator so that slicing by plan, region or month keeps the population consistent.

Risk measures

Risk scores are often stored as one row per member per risk period.

Average Risk Score :=
AVERAGEX(
    FactRiskScores,
    FactRiskScores[RiskScore]
)

High Risk Members Count := CALCULATE( DISTINCTCOUNT(FactRiskScores[MemberID]), KEEPFILTERS(FactRiskScores[RiskScore] >= 2.0) )

Adjust the high-risk threshold to your program’s definition. The important part is using DISTINCTCOUNT to avoid double-counting members across multiple risk periods when filtered by year.

Step 4: Handle Performance and Capacity for Large Claims Data

Insurance and healthcare claims data pushes Power BI harder than typical sales datasets. Performance tuning is not optional.

For DirectQuery claims tables

Focus on:

  • Source indexing

    • Ensure indexes on key filter and join columns (MemberID, ServiceDate, PaidDate, PlanID, ProviderID).
    • Work with DBAs to avoid non-sargable predicates (e.g., functions on date columns) in views used by Power BI.
  • Query reduction in reports

    • Use slicers and filters on high-selectivity columns (benefit year, product line) to reduce row counts early.
    • Avoid visuals that trigger multiple queries over the same DirectQuery table; limit the number of high-cardinality visuals per page.
  • Model simplification

    • Avoid calculated columns that perform row-by-row operations over DirectQuery tables; push those calculations into the source where possible.

For Import tables

Optimize VertiPaq usage:

  • Use appropriate data types (integers for IDs, true dates for dates, avoid text where numeric will do).
  • Remove unused columns from the dataset; each extra column increases memory footprint.
  • Use summarized history tables (e.g., member-month) instead of raw claim lines for older years.

Monitoring

On Premium capacity, use the built-in metrics app or Fabric monitoring:

  • Watch query durations and memory consumption per dataset.
  • If claims queries dominate the capacity, consider splitting models by audience (operations vs actuarial) with different refresh strategies.

Step 5: Row-Level Security for HIPAA and Internal Segmentation

Insurance and healthcare teams usually need strict access controls:

  • Operations sees detailed PHI for their region.
  • Utilization management sees clinical detail but only for assigned lines of business.
  • Actuarial may only need de-identified or aggregated views.

Implementing RLS in the model

Define roles in Power BI Desktop using filters on dimension tables, not facts:

  • Role: RegionOps

    • Filter on DimRegion: DimRegion[RegionCode] = "Midwest"
  • Role: PlanUM

    • Filter on DimPlan: DimPlan[UMAccessFlag] = TRUE()

Then publish and assign users to roles in the Power BI service.

Notes:

  • In DirectQuery, RLS filters are applied in the queries sent to the source, so indexing on those columns is important.
  • For scenarios where actuarial needs de-identified data, consider a separate dataset with masked or aggregated tables rather than relying solely on RLS.

Step 6: Build Separate Dashboards on One Model

With the semantic model in place, you can create multiple reports that share the same dataset:

  1. Claims Operations Dashboard

    • Visuals: open claims by status, average cycle time, paid vs allowed by adjuster, top providers by denial rate.
    • Measures: focus on Total Claims Paid, Total Claims Allowed, counts of open claims.
    • Filters: claim type, region, adjuster, service date.
  2. Utilization Management Dashboard

    • Visuals: admissions per 1,000 by plan, ED visits per 1,000, readmission rates, high-cost member lists.
    • Measures: Admissions per 1000, ED visits per 1,000, length of stay.
    • Filters: benefit year, plan, diagnosis group, provider.
  3. Risk & Actuarial Dashboard

    • Visuals: average risk score by plan, distribution of risk bands, loss ratio by risk segment.
    • Measures: Average Risk Score, High Risk Members Count, Loss Ratio.
    • Filters: risk period, plan, region, product line.

All three reports point to the same dataset. That keeps definitions consistent and reduces duplication, but you still manage layout, filters and drill-through separately for each audience.

Step 7: Fabric & Power BI User Group Leverage (Local Advantage)

In markets with a strong insurance and healthcare cluster, it’s common to have:

  • Shared Premium capacities across employers
  • Local user groups focused on Fabric & Power BI for insurance

Use that to your advantage:

  • Benchmark your model design against peers in similar regulatory and volume environments.
  • Compare different approaches to DirectQuery vs Import for claims and utilization.
  • Share patterns for risk score integration, especially when vendor feeds change structure.

For employer-sponsored buyers in a city like Chicago, the opportunity is to build a robust pattern once and then reuse it across lines of business and benefit years, rather than reinventing the model for every new program.

One Practical Takeaway

Before building your next claims or utilization dashboard, invest the time to define a single semantic model with clear grain, relationships and measures, and then hang multiple reports off that model. It’s the difference between endlessly patching slow, inconsistent reports and having a stable foundation that actuaries, clinicians and finance can all trust.

Editor's Note

This article reflects the shift from ad‑hoc claims reports to shared semantic models in Power BI and Fabric, particularly in insurance and healthcare analytics teams working on employer‑sponsored benefits in dense regional markets.

Professionals who want to apply these patterns to their own data can explore Excelgoodies' Power BI Training in Chicago, Illinois programme - taught live by instructors, with certification awarded once a real project is running at work.

Insights compiled through ongoing industry research and discussions within the Excelgoodies Analytics Community.

Power BI

New

Next Batches Now Live

Power BIPower BI
SQLSQL
Power AppsPower Apps
Power AutomatePower Automate
Microsoft FabricMicrosoft Fabrics
AzureAzure Data Engineering
Explore Dates & Reserve Your Spot → Reserve Your Spot →