Introduction to FHIR Profiling
FHIR profiling is the process of constraining and extending FHIR base resources to meet specific implementation requirements. This guide uses the "Learn, Build, Use" framework to help you master FHIR data modeling and profiling design.
What is FHIR Profiling?
Profiling allows you to adapt FHIR's generic resources for your specific use case by:
- Constraining: Making optional elements required, limiting value sets, or restricting cardinality
- Extending: Adding new elements that don't exist in the base resource
- Documenting: Providing clear usage guidance for implementers
- Validating: Ensuring data conforms to your business requirements
The Learn, Build, Use Framework
LEARN
Understand FHIR specifications, implementation guides, and existing patterns
BUILD
Design and create profiles that align with your business requirements
USE
Implement, validate, and iterate on your profiles in production
Phase 1: LEARN
Step 1: Understanding FHIR Base Specifications
Start with the Fundamentals
- Resource Structure: Every FHIR resource has:
- • Metadata (id, meta, implicitRules, language)
- • Narrative (text - human-readable summary)
- • Extensions (for additional data not in base spec)
- • Resource-specific elements (Patient.name, Observation.value, etc.)
- Data Types: Understand primitive types (string, integer, boolean) and complex types (CodeableConcept, Reference, Period)
- Cardinality: Elements can be 0..1 (optional), 1..1 (required), 0..* (optional repeating), or 1..* (required repeating)
Key Resources to Study
// Patient - Demographics and administrative information
// Observation - Measurements and simple assertions
// Condition - Problems, diagnoses
// Procedure - Events and interventions
// MedicationRequest - Prescriptions and orders
// Encounter - Interactions between patient and healthcare provider
// Organization - Healthcare providers, payers
// Practitioner - Healthcare professionalsStep 2: Aligning Business Goals with FHIR
Business Analysis Framework
What problem are you solving? Who are the stakeholders?
Example: "We need to exchange lab results between hospital labs and primary care physicians"
What information must be captured? What's optional vs. required?
Example: Test name, result value, reference ranges, performing lab, collection date
Which FHIR resources best represent your data?
Example: Observation (for results), DiagnosticReport (for report), Specimen (for sample)
What rules and validations does your business require?
Example: Result value must be present, status must be 'final' or 'amended'
Step 3: Research Implementation Guides
Don't reinvent the wheel! Research existing implementation guides (IGs) that address similar use cases.
US Core Implementation Guide
Foundational profiles for US healthcare. Start here for most US implementations.
View US Core IG →International Patient Summary
Global standard for patient summaries. Good for cross-border use cases.
View IPS IG →CARIN Blue Button
Payer data exchange profiles. Essential for claims and coverage data.
View CARIN BB IG →Da Vinci Project
Value-based care IGs including prior auth, care gaps, and risk adjustment.
View Da Vinci IGs →Research Checklist:
- ✓ Does an existing IG already solve my use case?
- ✓ What profiles from existing IGs can I reuse?
- ✓ What terminology (value sets, code systems) is already standardized?
- ✓ What extensions are commonly used in my domain?
- ✓ What are the conformance expectations (SHALL, SHOULD, MAY)?
Phase 2: BUILD
Step 4: Design Your Profile
Now that you've learned FHIR and researched existing patterns, it's time to design your profile.
Profile Design Principles
- 1. Start Simple, Then Constrain
Begin with the base resource. Add constraints incrementally based on real requirements.
- 2. Reuse Before Creating
Use existing profiles (like US Core) as your base. Only create new profiles when necessary.
- 3. Make Required What Must Be Required
Only set min=1 (required) if the data is truly essential. Over-constraining makes adoption difficult.
- 4. Use Standard Terminologies
Leverage LOINC, SNOMED CT, RxNorm, and other standard code systems wherever possible.
- 5. Document Everything
Clear definitions and usage notes are crucial for implementer success.
Example: Lab Result Profile
Let's design a profile for lab results that builds on US Core Observation Lab:
{
"resourceType": "StructureDefinition",
"url": "http://example.org/fhir/StructureDefinition/lab-result",
"name": "LabResult",
"title": "Laboratory Result Profile",
"status": "draft",
"description": "Profile for lab test results in our system",
"fhirVersion": "4.0.1",
"kind": "resource",
"abstract": false,
"type": "Observation",
"baseDefinition": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-observation-lab",
"derivation": "constraint",
"differential": {
"element": [
{
"id": "Observation.status",
"path": "Observation.status",
"short": "Result status",
"definition": "Status of the lab result",
"mustSupport": true,
"binding": {
"strength": "required",
"valueSet": "http://example.org/fhir/ValueSet/lab-result-status"
}
},
{
"id": "Observation.category",
"path": "Observation.category",
"min": 1,
"mustSupport": true,
"patternCodeableConcept": {
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "laboratory"
}]
}
},
{
"id": "Observation.code",
"path": "Observation.code",
"short": "Lab test code (LOINC preferred)",
"mustSupport": true,
"binding": {
"strength": "extensible",
"valueSet": "http://example.org/fhir/ValueSet/lab-test-codes"
}
},
{
"id": "Observation.value[x]",
"path": "Observation.value[x]",
"short": "Result value",
"min": 1,
"mustSupport": true
},
{
"id": "Observation.interpretation",
"path": "Observation.interpretation",
"short": "High, low, normal, etc.",
"mustSupport": true
},
{
"id": "Observation.referenceRange",
"path": "Observation.referenceRange",
"short": "Reference range for result interpretation",
"min": 0,
"max": "*",
"mustSupport": true
},
{
"id": "Observation.performer",
"path": "Observation.performer",
"short": "Laboratory that performed the test",
"min": 1,
"type": [{
"code": "Reference",
"targetProfile": [
"http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization"
]
}],
"mustSupport": true
}
]
}
}Key Profile Elements Explained:
- baseDefinition: We build on US Core Observation Lab (don't start from scratch!)
- derivation: constraint: We're constraining, not creating a new resource type
- min: 1: Makes optional elements required for our use case
- mustSupport: true: Implementers must be able to process this element
- binding.strength: How strictly codes must match the value set (required, extensible, preferred, example)
Step 5: Define Extensions
When FHIR base resources don't have an element you need, create an extension:
{
"resourceType": "StructureDefinition",
"url": "http://example.org/fhir/StructureDefinition/lab-urgency",
"name": "LabUrgency",
"title": "Lab Test Urgency Extension",
"status": "draft",
"kind": "complex-type",
"abstract": false,
"context": [{
"type": "element",
"expression": "Observation"
}],
"type": "Extension",
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Extension",
"derivation": "constraint",
"differential": {
"element": [{
"id": "Extension",
"path": "Extension",
"short": "Lab test urgency level",
"definition": "Indicates the clinical urgency of the lab test (routine, urgent, stat)",
"max": "1"
}, {
"id": "Extension.url",
"path": "Extension.url",
"fixedUri": "http://example.org/fhir/StructureDefinition/lab-urgency"
}, {
"id": "Extension.value[x]",
"path": "Extension.value[x]",
"type": [{
"code": "code"
}],
"binding": {
"strength": "required",
"valueSet": "http://example.org/fhir/ValueSet/lab-urgency-codes"
}
}]
}
}
// Usage in an Observation:
{
"resourceType": "Observation",
"id": "lab-example",
"extension": [{
"url": "http://example.org/fhir/StructureDefinition/lab-urgency",
"valueCode": "stat"
}],
// ... rest of observation
}Step 6: Create Value Sets
Value sets define the allowed codes for coded elements:
{
"resourceType": "ValueSet",
"url": "http://example.org/fhir/ValueSet/lab-result-status",
"name": "LabResultStatus",
"title": "Lab Result Status Codes",
"status": "draft",
"description": "Allowed status values for lab results",
"compose": {
"include": [{
"system": "http://hl7.org/fhir/observation-status",
"concept": [
{
"code": "final",
"display": "Final"
},
{
"code": "amended",
"display": "Amended"
},
{
"code": "corrected",
"display": "Corrected"
},
{
"code": "preliminary",
"display": "Preliminary"
}
]
}]
}
}Phase 3: USE
Step 7: Validation and Testing
Validation Strategy
- 1. Use the FHIR Validator
java -jar validator_cli.jar \ -version 4.0.1 \ -ig your-implementation-guide.json \ -profile http://example.org/fhir/StructureDefinition/lab-result \ patient-example.json - 2. Create Test Fixtures
Build a library of valid and invalid examples to test your profiles
- 3. Automate Validation
Integrate validation into your CI/CD pipeline
- 4. Test Edge Cases
Minimum data, maximum data, optional elements, extensions
Example: Valid Lab Result
{
"resourceType": "Observation",
"id": "lab-glucose-example",
"meta": {
"profile": [
"http://example.org/fhir/StructureDefinition/lab-result"
]
},
"extension": [{
"url": "http://example.org/fhir/StructureDefinition/lab-urgency",
"valueCode": "routine"
}],
"status": "final",
"category": [{
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "laboratory",
"display": "Laboratory"
}]
}],
"code": {
"coding": [{
"system": "http://loinc.org",
"code": "2339-0",
"display": "Glucose [Mass/volume] in Blood"
}],
"text": "Blood Glucose"
},
"subject": {
"reference": "Patient/example",
"display": "Jane Doe"
},
"effectiveDateTime": "2025-01-15T08:30:00Z",
"issued": "2025-01-15T09:45:00Z",
"performer": [{
"reference": "Organization/lab-acme",
"display": "ACME Laboratory Services"
}],
"valueQuantity": {
"value": 95,
"unit": "mg/dL",
"system": "http://unitsofmeasure.org",
"code": "mg/dL"
},
"interpretation": [{
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation",
"code": "N",
"display": "Normal"
}]
}],
"referenceRange": [{
"low": {
"value": 70,
"unit": "mg/dL",
"system": "http://unitsofmeasure.org",
"code": "mg/dL"
},
"high": {
"value": 100,
"unit": "mg/dL",
"system": "http://unitsofmeasure.org",
"code": "mg/dL"
},
"type": {
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/referencerange-meaning",
"code": "normal",
"display": "Normal Range"
}]
}
}]
}Step 8: Implementation and Iteration
Implementation Checklist:
- □ Publish Your Implementation Guide
Use the FHIR IG Publisher to create browsable documentation
- □ Provide Example Resources
Include valid examples for each profile
- □ Document Conformance Expectations
Clear SHALL/SHOULD/MAY requirements
- □ Set Up a Test Server
Allow implementers to test against your profiles
- □ Gather Feedback
Iterate based on real-world implementation experience
- □ Version Your Profiles
Use semantic versioning to manage changes
Best Practices Summary
✓ DO
- ✅ Start with existing IGs and profiles
- ✅ Use standard terminologies (LOINC, SNOMED, RxNorm)
- ✅ Keep profiles as simple as possible
- ✅ Provide clear documentation and examples
- ✅ Test thoroughly with real data
- ✅ Version your profiles appropriately
- ✅ Engage with the FHIR community
- ✅ Use mustSupport judiciously
- ✅ Consider backward compatibility
- ✅ Document your design decisions
✗ DON'T
- ❌ Over-constrain optional elements
- ❌ Create custom code systems unnecessarily
- ❌ Profile without understanding the base resource
- ❌ Ignore existing implementation patterns
- ❌ Skip validation and testing
- ❌ Make breaking changes in minor versions
- ❌ Create extensions for data that fits existing elements
- ❌ Use too many nested extensions
- ❌ Forget about implementer experience
- ❌ Profile in isolation without stakeholder input
Tools & Resources
Essential Tools
- Simplifier.net
Profile editor and IG publishing platform
- Forge by Firely
Desktop profile editor
- FSH School
Learn FHIR Shorthand for faster profiling
- FHIR IG Publisher
Generate implementation guide websites
Learning Resources
- FHIR Profiling Documentation
Official HL7 profiling guide
- Implementation Guide Resource
How to structure IGs
- IG Authoring Best Practices
Guidance from the FHIR community
- FHIR Community Chat
Get help from FHIR experts
Need Help with FHIR Profiling?
Our experts can help you design, validate, and implement FHIR profiles tailored to your organization's specific requirements.