Building a National FHIR R4 Platform for 20,000+ US Skilled Nursing Facilities — with QAPI & CMS 5-Star Automation
How we connected 20,000+ SNFs across the United States into a single Azure Health Data Services FHIR R4 lake, automated the CMS 5-Star Rating computation, built a QAPI compliance dashboard, and shipped an Agentic Medical Director AI that monitors every facility around the clock.
The Scale Problem: 20,000+ SNFs, 20,000+ Data Silos
There are roughly 15,000–16,000 certified SNFs in the United States today — Octdaily works with 20,000+ post-acute care facilities in total. Each one runs a different EHR: PointClickCare, MatrixCare, Netsmart, American HealthTech, or a homegrown system — all exporting clinical data in HL7 v2.x ADT, ORU, and MDS 3.0 formats that haven't fundamentally changed since the 1990s.
Our mandate at Octdaily: connect every one of them into a single FHIR R4 data warehouse, power a national QAPI compliance platform, automate the CMS 5-Star Rating computation, and ship an AI agent that acts as a Medical Director for each facility — 24/7, at scale.
System Architecture
20,000+ SNFs (PointClickCare, MatrixCare, Netsmart, AHT...)
│ HL7 v2 ADT / ORU / MDS 3.0
▼
Azure Event Hubs (per-facility partitioning, 1M+ msgs/day)
│
▼
Azure Functions — HL7 → FHIR R4 Mapper (C# + Firely SDK)
│ Validated FHIR R4 Transaction Bundles
▼
Azure Health Data Services (FHIR R4 Server — multi-tenant)
│ FHIR REST API + $everything + bulk export
├──► QAPI Compliance Engine (.NET 8 worker)
├──► CMS 5-Star Rating Engine (.NET 8 worker)
├──► Agentic Medical Director (Claude + GPT-4o)
└──► 10+ EMR Micro-Apps (Angular 17 Module Federation)Part 1 — FHIR R4 Data Warehouse
HL7 ADT → FHIR Patient + Encounter
public class AdtA01ToFhirMapper : IHl7Mapper<AdtA01Message>
{
public Bundle Map(AdtA01Message msg)
{
var patient = new Patient
{
Id = msg.PatientId.ToFhirId(),
Name = [new HumanName { Family = msg.PatientName.LastName,
Given = [msg.PatientName.FirstName] }],
BirthDate = msg.DateOfBirth.ToFhirDate(),
Identifier = [new Identifier { System = "urn:oid:2.16.840.1.113883.4.1",
Value = msg.Ssn }]
};
var encounter = new Encounter
{
Subject = new ResourceReference("Patient/" + patient.Id),
Status = Encounter.EncounterStatus.InProgress,
Class = new Coding("http://terminology.hl7.org/CodeSystem/v3-ActCode", "IMP"),
Period = new Period { Start = msg.AdmissionDate.ToFhirDateTime() }
};
return FhirBundleBuilder.Transaction(patient, encounter);
}
}MDS 3.0 → FHIR Observations (Quality Measures)
MDS 3.0 assessments are the raw input for CMS Quality Measures. We mapped every relevant section:
- Section GG (functional abilities & goals) → Observation (LOINC 83254-7)
- Section J (health conditions / falls) → Condition + Observation
- Section K (nutritional status / weight loss) → Observation (LOINC 29463-7)
- Section N (medications / antipsychotic use) → MedicationRequest
- Section O (special treatments / rehospitalisation) → Encounter + Procedure
Part 2 — QAPI Compliance Platform
QAPI (Quality Assurance and Performance Improvement) is mandated by CMS for all certified SNFs. Our platform automates the entire QAPI lifecycle:
What QAPI Tracks
- Infection rates (UTI, C. diff, respiratory) vs. national benchmarks
- Rehospitalisation rates (30-day and 90-day)
- Pressure injury prevalence (new and worsening wounds)
- Fall rates with and without injury
- Antipsychotic use in residents without psychosis diagnosis
- Resident weight loss >5% in 30 days or >10% in 180 days
- Chemical restraint monitoring
PDSA Cycle Automation
Our QAPI engine auto-generates PDSA (Plan-Do-Study-Act) improvement plans when a metric breaches threshold:
public async Task EvaluateQapiThresholdsAsync(string facilityId)
{
var metrics = await _metricsService.GetCurrentMetricsAsync(facilityId);
foreach (var metric in metrics.Where(m => m.IsBelowThreshold))
{
var plan = await _qapiPlanGenerator.GenerateAsync(new QapiContext
{
FacilityId = facilityId,
MetricCode = metric.Code,
CurrentRate = metric.Rate,
Benchmark = metric.NationalBenchmark,
TrendData = metric.Last12Months
});
await _notificationService.AlertQapiTeamAsync(facilityId, plan);
await _fhirClient.CreateAsync(plan.ToFhirTask());
}
}Part 3 — CMS 5-Star Quality Rating Engine
The CMS 5-Star system rates every nursing home on three equally-weighted pillars:
| Pillar | Data Source | Weight | |--------|------------|--------| | Health Inspections | State survey results | 1/3 | | Staffing | PBJ (Payroll-Based Journal) submission | 1/3 | | Quality Measures | MDS 3.0 assessments | 1/3 |
Automated Computation Pipeline
public async Task<StarRating> ComputeFiveStarRatingAsync(string facilityId)
{
// Pillar 1: Health Inspection score from CMS Care Compare feed
var inspectionScore = await _inspectionService.GetScoreAsync(facilityId);
// Pillar 2: Staffing — RN hours/resident/day + total staffing
var pbj = await _pbjService.GetStaffingMetricsAsync(facilityId);
var staffingScore = _staffingScorer.ComputeScore(pbj);
// Pillar 3: Quality Measures — 15 short-stay + 16 long-stay MDS measures
var qmScores = await _qmService.ComputeAllMeasuresAsync(facilityId);
var qmScore = _qmScorer.ComputeOverall(qmScores);
// Weighted composite → 1-5 star rating
return _ratingCalculator.Calculate(inspectionScore, staffingScore, qmScore);
}Our dashboard shows each facility's current star rating, the delta from the prior quarter, which pillar is dragging the score, and a predictive forecast of what actions would move the rating.
Part 4 — Agentic Medical Director
The most innovative piece: an LLM-powered agent that behaves like a virtual Medical Director for each facility.
What the Agent Does
- Monitors all QAPI metrics in real time across every facility
- Identifies residents at risk of rehospitalisation (using predictive risk scores from MDS data)
- Generates facility-specific improvement recommendations aligned to the PDSA cycle
- Drafts CMS deficiency response letters (Plans of Correction) from inspection findings
- Answers clinical staff queries: "Why is our fall rate above the state average?"
- Escalates critical alerts (e.g. infection cluster detected) with recommended interventions
Agent Architecture (Claude + GPT-4o)
public class AgenticMedicalDirector
{
public async Task<DirectorResponse> RunAsync(FacilityContext ctx)
{
// 1. Pull current FHIR data for this facility
var snapshot = await _fhirService.GetFacilitySnapshotAsync(ctx.FacilityId);
// 2. Build structured prompt with clinical context
var prompt = _promptBuilder.Build(new MedicalDirectorPrompt
{
QapiMetrics = snapshot.QapiMetrics,
FiveStarRating = snapshot.CurrentRating,
AtRiskResidents = snapshot.AtRiskResidents,
RecentIncidents = snapshot.Last30DayIncidents,
PendingDeficiency = snapshot.OpenCmsDeficiencies
});
// 3. Run Claude for clinical reasoning (long context, nuanced)
var analysis = await _claude.CompleteAsync(prompt, model: "claude-opus-4-5");
// 4. Run GPT-4o for structured action plan output (JSON schema)
var actionPlan = await _openAi.StructuredOutputAsync<QapiActionPlan>(
analysis.Summary, responseFormat: QapiActionPlan.Schema);
return new DirectorResponse { Analysis = analysis, ActionPlan = actionPlan };
}
}Results at Octdaily
- 20,000+ SNFs connected to a single FHIR R4 endpoint in the US
- 10+ EMR micro-apps consuming unified patient records with SMART on FHIR scopes
- CMS 5-Star ratings computed and surfaced within 24 hours of new MDS submission
- QAPI breach alerts delivered <60 seconds after metric threshold crossed
- Agentic Medical Director handles thousands of facility queries per day autonomously
- Zero PHI leakage across tenant boundaries — enforced at the FHIR authorization layer