Short answer: the base FHIR resources are deliberately loose: almost everything is optional and most codes are only examples, so that one standard fits every country. A profile is a StructureDefinition that tightens a resource for one use: in this context, Patient must have an identifier of this type, Observation.code must be a LOINC code from this list, this element must be supported, that one may not appear. An extension adds an element the base resource lacks, identified by a URL and defined by its own StructureDefinition. Implementation guides (US Core, the IPS, national guides) are collections of profiles, extensions, value sets and examples. A resource says which profiles it claims to follow in meta.profile, and a validator checks it.
What a profile can change
A FHIR profile can change a resource only by narrowing it: tightening cardinality, marking elements as must-support, fixing values or patterns, binding elements to value sets with a strength, slicing lists into named parts, restricting choice types, adding FHIRPath invariants and limiting reference targets. A profile cannot add elements, rename anything or loosen the base specification.
| Constraint | What it does | Example |
|---|---|---|
| Cardinality | Make optional elements required, or forbid them | Patient.identifier 1..*; Patient.photo 0..0 |
| Must support | Receivers must be able to store and display the element if sent | US Core marks birthDate as must-support |
| Fixed value or pattern | Lock an element to one value | Observation.category fixed to vital-signs |
| Binding | Point an element at a value set with a strength | Observation.code bound to the vital signs list, required |
| Slicing | Split a list into named parts with their own rules | Blood pressure: component sliced into systolic and diastolic |
| Type restriction | Limit a choice | value[x] restricted to valueQuantity |
| Invariant | A FHIRPath rule that must hold | "effective[x] must be present" or "value or dataAbsentReason" |
| Reference target | Limit what a reference may point to | subject only Patient, and only patients conforming to this profile |
A profile can only narrow. It cannot add elements (that is what extensions are for), rename anything or loosen the base.
Binding strength
FHIR defines four binding strengths. required: the code must come from the value set. extensible: use the value set if a concept fits; otherwise another code is allowed. preferred: recommended, not enforced. example: illustrative only, which is what most base resources have. Misreading extensible as required is a common source of false validation errors.
A readable profile excerpt
A FHIR profile is a StructureDefinition whose differential lists only the constraints that differ from the base resource, while its snapshot lists every element. The readable excerpt below constrains Observation to a home blood pressure: the code is fixed to LOINC 85354-9 and component is sliced into exactly one systolic and one diastolic part.
A profile's differential lists only what changed from the base; the snapshot lists everything. This differential says that a blood pressure Observation must carry LOINC 85354-9 and exactly two components:
{
"resourceType": "StructureDefinition",
"url": "https://example.org/fhir/StructureDefinition/bp-home",
"name": "HomeBloodPressure",
"status": "active",
"kind": "resource",
"abstract": false,
"type": "Observation",
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Observation",
"derivation": "constraint",
"differential": {"element": [
{"id": "Observation.code", "path": "Observation.code",
"patternCodeableConcept": {"coding": [{"system": "http://loinc.org", "code": "85354-9"}]}},
{"id": "Observation.component", "path": "Observation.component", "min": 2, "max": "2",
"slicing": {"discriminator": [{"type": "pattern", "path": "code"}], "rules": "closed"}},
{"id": "Observation.component:systolic", "path": "Observation.component", "sliceName": "systolic", "min": 1, "max": "1"},
{"id": "Observation.component:systolic.code", "path": "Observation.component.code",
"patternCodeableConcept": {"coding": [{"system": "http://loinc.org", "code": "8480-6"}]}},
{"id": "Observation.component:diastolic", "path": "Observation.component", "sliceName": "diastolic", "min": 1, "max": "1"},
{"id": "Observation.component:diastolic.code", "path": "Observation.component.code",
"patternCodeableConcept": {"coding": [{"system": "http://loinc.org", "code": "8462-4"}]}}
]}
}
Profiles are rarely written by hand; authors use FHIR Shorthand (FSH) with SUSHI, or tools such as Forge and Simplifier, and publish with the HL7 IG Publisher. Guides are distributed as packages (hl7.fhir.us.core#6.1.0, hl7.fhir.uv.ips#1.1.0) that validators and servers load.
Extensions
An extension is a key-value element placed in extension (or modifierExtension when it changes the meaning of the resource and must not be ignored). Its url is the canonical URL of its StructureDefinition; its value is one typed value[x], or nested extensions. Birth place is an HL7-defined extension on Patient:
{
"resourceType": "Patient",
"id": "example",
"extension": [{
"url": "http://hl7.org/fhir/StructureDefinition/patient-birthPlace",
"valueAddress": {"city": "Lyon", "country": "FR"}
}],
"name": [{"family": "Doe", "given": ["Jane"]}]
}
Rules of good practice: look for an existing extension (HL7's registry and the national guides) before defining one; give it a URL under a domain you control; define it in a StructureDefinition so others can validate it; never use an extension for something a base element already covers.
meta.profile and validation
meta.profile is the list of canonical URLs a FHIR resource claims to conform to, and claiming is not proving. A validator checks the resource against the base specification and against each claimed profile, or against a profile you name. The HL7 reference validator runs locally with packages, and FHIR servers expose a $validate operation that accepts a profile parameter.
meta.profile lists the canonical URLs a resource claims to conform to. Claiming is not proving: a validator checks the resource against the base specification and against every profile claimed (or against a profile you ask it to use). The HL7 reference validator (validator_cli.jar) runs locally and loads packages; servers offer POST /Observation/$validate?profile=…; the IG Publisher validates all examples in a guide. A resource may conform to several profiles at once (a national Patient profile and the IPS Patient) as long as they do not contradict.
Two practical rules: a server that declares a profile in its CapabilityStatement should reject resources that fail it; a client that receives resources should not reject unknown extensions or extra elements that a profile did not forbid, because the base specification allows them.
In Anpheros
Anpheros Platform is a FHIR R4 server that uses LOINC for observations, ATC for medications and SNOMED CT where applicable, and offers a free validator that checks a resource's structure against FHIR R4. When a clinic sends resources with meta.profile set to a national or IPS profile, the claim is preserved so a downstream system can validate against it.
The free validator is on the developer site. For the guides themselves, see FHIR implementation guides explained.
Related pages
- FHIR implementation guides explained
- CodeableConcept and Coding in FHIR
- FHIR Observation explained
- FHIR Patient resource explained
- Terminology servers explained
- FHIR validator (developer site)
Sources
- HL7 FHIR R4: Profiling FHIR
- HL7 FHIR R4: Extensibility
- HL7 FHIR R4: StructureDefinition
- HL7 FHIR R4: Terminology bindings
- HL7 FHIR Shorthand
- HL7 FHIR validator
- HL7 FHIR R4: patient-birthPlace extension
Frequently asked questions
Can a profile add a new element to a resource?
No. Profiles only constrain. New data goes in an extension, which the profile can then require or forbid like any other element.
What does must-support actually require?
The implementation guide defines it; typically that a sender populates the element when it has the data and a receiver stores and can display it. It does not make the element mandatory.
If a resource has no meta.profile, is it invalid?
No. meta.profile is a claim, not a requirement. A server or guide may require it; the base specification does not. Validators can be asked to check against a profile the resource does not declare.
How do I know which profile to use in my country?
Each national FHIR community publishes a core guide (US Core, UK Core, nl-core, the German Basisprofile, and so on); the implementation guides page explains how to find them. Cross-border summaries use the IPS.
Try it free in the sandbox
Your first FHIR call in 5 minutes. An HL7 FHIR R4 API with the patient's consent built in: try it in the sandbox, then connect your own app or clinic system.
Free · 30 synthetic patients · no card

The more you log, the clearer your record
Your health history in one place, under your control.
Free · Works in your browser · No card
