FHIR Data Validation: How `$validate` Actually Works in Production

FHIR Data Validation: How $validate Actually Works in Production

Diagram: FHIR Data Validation: How `$validate` Actually Works in Production. Diagram illustrating the article's core structure and decision points.

FHIR `$validate` operation validates a resource against a profile and returns an OperationOutcome. In production the operation is invoked in three modes, each with different semantics and different failure modes.

Mode 1: Write-time validation. POST or PUT with x-fhir-request-headers: return=OperationOutcome. The server validates, rejects on error, and returns the OperationOutcome with issues. Best for strict data quality gates.

Mode 2: Standalone $validate on a resource. POST to /{resourceType}/$validate with the resource in the body. Server returns OperationOutcome without persisting. Best for pre-commit validation in CI or client-side checking.

Mode 3: $validate against a specific profile. Same as mode 2 but with ?profile={URL}. Validates against the named profile instead of the resource's default. Best for cross-profile compatibility testing.

What $validate actually checks

1. Structural conformance — required elements present, correct data types, correct cardinality. 2. Terminology binding — coded values valid against bound ValueSets. Requires terminology server integration. 3. Invariant expressions — FHIRPath invariants defined in the profile. 4. Extension conformance — extensions match their StructureDefinitions.

Common validation failures

Failure Frequency Fix
Missing required element ~40% of errors Upstream data quality
Terminology binding mismatch ~30% of errors Update code system, expand ValueSet
Invariant violation ~15% of errors Review FHIRPath expression
Extension URL mismatch ~10% of errors Reference correct StructureDefinition

Performance considerations

$validate with terminology binding checks adds 50-200ms per resource depending on ValueSet size and server tuning. For high-volume writes, cache validated code lookups; for batch validation, run async via Bulk Data validation patterns.

Vendor state (mid-2026)

Server Structural Terminology Invariants Extensions
HAPI JPA 7.x Full Full Full Full
Aidbox 2409 Full Full Full Full
Medplum 3.x Full Basic Full Full
Inferno (open validator) Full Full Full Full

$validate is one of the most under-used operations in FHIR. Wire it into every write path and every CI pipeline; the data quality lift is significant.

Marcus Chen

Health-tech product analyst from Seattle. Focused on payer interoperability, prior authorization, and where the friction really lives.