
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.