DL
Back to Blog
TechFebruary 2, 2026·5 min read

Clinical Reference Ranges and Interpretation Codes

FhirHub implements clinical reference ranges based on AHA, ADA, and KDIGO guidelines to automatically compute FHIR interpretation codes, turning raw measurements into actionable clinical context.

D

David Le

Clinical Reference Ranges and Interpretation Codes

By David Le -- Part 7 of the FhirHub Series

A blood pressure reading of 138/88 means nothing without context. Is that high? Critical? Normal for this patient? FhirHub implements clinical reference ranges based on published guidelines (AHA, ADA, KDIGO) and uses them to compute FHIR interpretation codes automatically.

Why Reference Ranges Matter

In clinical practice, every measurement has a normal range. Values outside that range trigger different levels of concern:

  • Normal (N) -- Within expected bounds
  • High (H) / Low (L) -- Outside normal, requires attention
  • Critically High (HH) / Critically Low (LL) -- Immediate clinical action needed

FHIR represents these as interpretation codes on Observation resources. FhirHub computes them client-side using the clinical rules engine in frontend/src/lib/clinical-rules.ts.

Vital Signs Reference Ranges

FhirHub defines normal and critical ranges for each vital sign by LOINC code:

export const VITAL_REFERENCE_RANGES: Record<string, VitalRanges | null> = {
  // Systolic Blood Pressure (mmHg) - AHA Guidelines
  ["8480-6"]: {
    normal: { low: 90, high: 120 },
    critical: { low: 70, high: 180 },
    unit: "mmHg",
  },
  // Diastolic Blood Pressure (mmHg)
  ["8462-4"]: {
    normal: { low: 60, high: 80 },
    critical: { low: 40, high: 120 },
    unit: "mmHg",
  },
  // Heart Rate (bpm)
  ["8867-4"]: {
    normal: { low: 60, high: 100 },
    critical: { low: 40, high: 150 },
    unit: "bpm",
  },
  // Body Temperature (°F)
  ["8310-5"]: {
    normal: { low: 97.8, high: 99.1 },
    critical: { low: 95, high: 104 },
    unit: "degF",
  },
  // Respiratory Rate (breaths/min)
  ["9279-1"]: {
    normal: { low: 12, high: 20 },
    critical: { low: 8, high: 30 },
    unit: "/min",
  },
  // Oxygen Saturation (%)
  ["2708-6"]: {
    normal: { low: 95, high: 100 },
    critical: { low: 85 },
    unit: "%",
  },
  // Body Weight - no standard range
  ["29463-7"]: null,
};

Note that body weight has no standard range (null) -- it varies too much by individual. The system handles this gracefully by skipping interpretation for vitals without defined ranges.

AHA Blood Pressure Categories

Blood pressure interpretation follows the American Heart Association (AHA) guidelines, which define six categories based on the combination of systolic and diastolic values:

export function computeBPInterpretation(
  systolic: number,
  diastolic: number
): { category: string; interpretation: InterpretationDTO } {
  // Hypertensive Crisis (Critical high)
  if (systolic >= 180 || diastolic >= 120) {
    return {
      category: "Hypertensive Crisis",
      interpretation: createInterpretation("HH"),
    };
  }

  // Severe Hypotension (Critical low)
  if (systolic < 70 || diastolic < 40) {
    return {
      category: "Severe Hypotension",
      interpretation: createInterpretation("LL"),
    };
  }

  // Stage 2 Hypertension
  if (systolic >= 140 || diastolic >= 90) {
    return {
      category: "Stage 2 Hypertension",
      interpretation: createInterpretation("H"),
    };
  }

  // Stage 1 Hypertension
  if (systolic >= 130 || diastolic >= 80) {
    return {
      category: "Stage 1 Hypertension",
      interpretation: createInterpretation("H"),
    };
  }

  // Elevated
  if (systolic >= 120 && diastolic < 80) {
    return {
      category: "Elevated",
      interpretation: createInterpretation("H"),
    };
  }

  // Hypotension
  if (systolic < 90 || diastolic < 60) {
    return {
      category: "Hypotension",
      interpretation: createInterpretation("L"),
    };
  }

  // Normal
  return {
    category: "Normal",
    interpretation: createInterpretation("N"),
  };
}

The AHA categories mapped to FHIR interpretation codes:

CategorySystolicDiastolicFHIR Code
Normal< 120AND < 80N
Elevated120-129AND < 80H
Stage 1 Hypertension130-139OR 80-89H
Stage 2 Hypertension>= 140OR >= 90H
Hypertensive Crisis>= 180OR >= 120HH
Hypotension< 90OR < 60L
Severe Hypotension< 70OR < 40LL

Lab Reference Ranges

FhirHub defines reference ranges for 21+ common lab tests:

export const LAB_REFERENCE_RANGES = {
  glucose:          { normal: { low: 70, high: 100 },  critical: { low: 50, high: 400 },  unit: "mg/dL" },
  hba1c:            { normal: { low: 4.0, high: 5.6 },                                     unit: "%" },
  bun:              { normal: { low: 7, high: 20 },    critical: { low: 2, high: 100 },    unit: "mg/dL" },
  creatinine:       { normal: { low: 0.7, high: 1.3 }, critical: { high: 10 },             unit: "mg/dL" },
  egfr:             { normal: { low: 60, high: 120 },  critical: { low: 15 },              unit: "mL/min/1.73m2" },
  sodium:           { normal: { low: 136, high: 145 }, critical: { low: 120, high: 160 },  unit: "mEq/L" },
  potassium:        { normal: { low: 3.5, high: 5.0 }, critical: { low: 2.5, high: 6.5 },  unit: "mEq/L" },
  totalCholesterol: { normal: { high: 200 },                                                unit: "mg/dL" },
  ldlCholesterol:   { normal: { high: 100 },                                                unit: "mg/dL" },
  hdlCholesterol:   { normal: { low: 40 },                                                  unit: "mg/dL" },
  triglycerides:    { normal: { high: 150 },                                                unit: "mg/dL" },
  troponinI:        { normal: { high: 0.04 },                                               unit: "ng/mL" },
  bnp:              { normal: { high: 100 },                                                unit: "pg/mL" },
  inr:              { normal: { low: 2.0, high: 3.0 },                                     unit: "" },
  inrTherapeutic:   { normal: { low: 2.0, high: 3.0 }, critical: { low: 1.5, high: 4.0 },  unit: "" },
  inrBaseline:      { normal: { low: 0.9, high: 1.1 },                                     unit: "" },
  pt:               { normal: { low: 11, high: 13.5 },                                     unit: "s" },
};

Key details:

  • Not all ranges are symmetric. HDL cholesterol only has a low threshold (higher is better). Troponin I only has a high threshold (any elevation is concerning).
  • Some tests have multiple range profiles. INR has three: therapeutic range (for patients on anticoagulation), baseline (for patients not on anticoagulation), and a general range.
  • Critical ranges are optional. HbA1c doesn't define critical thresholds -- any abnormal value warrants attention but isn't immediately dangerous.

Computing Interpretations

The interpretation engine converts a numeric value into a FHIR interpretation code:

export function computeVitalInterpretation(
  loincCode: string,
  value: number
): InterpretationDTO {
  const referenceRange = getVitalReferenceRange(loincCode);
  const criticalRange = getVitalCriticalRange(loincCode);

  return computeInterpretation(value, referenceRange, criticalRange);
}

The computeInterpretation utility checks the value against both the normal and critical ranges, returning the appropriate FHIR interpretation code (N, H, L, HH, LL).

FHIR ReferenceRange DTOs

Reference ranges are converted to FHIR-compliant DTOs for API communication:

export function getVitalReferenceRange(
  loincCode: string
): ReferenceRangeDTO | undefined {
  const ranges = VITAL_REFERENCE_RANGES[loincCode];
  if (!ranges) return undefined;

  return {
    low: ranges.normal.low !== undefined
      ? { value: ranges.normal.low, unit: ranges.unit, system: UCUM_SYSTEM }
      : undefined,
    high: ranges.normal.high !== undefined
      ? { value: ranges.normal.high, unit: ranges.unit, system: UCUM_SYSTEM }
      : undefined,
    type: "normal",
  };
}

Units use the UCUM (Unified Code for Units of Measure) system, which is the standard coding system for units in FHIR.

Clinical Alerts

The reference ranges power FhirHub's clinical alerts system. When a vital sign or lab result falls outside normal ranges, the system generates an alert visible on the dashboard. Critical values (HH/LL) are surfaced with higher priority.

What's Next

In Part 8, we'll examine the bulk data export feature -- from the 4-step wizard UI to the job lifecycle management in the API.


Find the source code on GitHub Connect on LinkedIn

Related Projects

Featured

FhirHub

A healthcare data management platform built on the HL7 FHIR R4 standard, providing a comprehensive web interface for managing patient clinical data including vitals, conditions, medications, lab orders, and bulk data exports with role-based access control and full audit logging.

Next.js 16
React 19
Typescript
Tailwind CSS 4
+8