UCUM covers real physical quantities well. "Voids per shift", "steps per day since discharge", "medication administrations per encounter" — clinical events per organizational time bucket — are not physical quantities and not in UCUM. The FHIR spec has an answer for that gap, but it is a specific pattern that many teams miss. The site's Clinical UCUM unit converter recognises canonical UCUM only and leaves arbitrary counts to a different mechanism. For the wider FHIR framing, our broader FHIR coverage has more.
The Two Options FHIR Gives You
- Curly-brace annotation on a UCUM base —
{voids}/8.hfor voids per eight-hour shift - Non-Quantity value shape —
Observation.valueString,valueCodeableConcept, orvalueIntegerwith a code
Both are valid FHIR. Each has different downstream implications.
When Annotation Works
If the underlying quantity is a real number with dimensional meaning — a count per time — annotation on a UCUM unit is the safest choice.
{voids}/8.h — the base is per-time; the count is annotated. Downstream converters that ignore annotations still know they are dealing with a per-time rate. Downstream systems that read the annotation get the human context.
For the canonical set to build on, canonical UCUM units the FHIR spec assumes you'll use is the entry.
When Annotation Doesn't Work
Some "units" are not units at all. Care team names ("per nurse"), organizational buckets ("per shift" without a defined duration), or classification tiers (mild/moderate/severe) do not have numeric dimension.
For these, use valueString, valueCodeableConcept, or valueInteger — not valueQuantity with a fake unit. Forcing them into UCUM produces payloads that downstream unit converters mangle.
The valueInteger Pattern
For clean counts without a per-time dimension — "number of missed doses" — valueInteger is the right shape. Do not attach a fake unit.
Downstream logic that expects a Quantity has to be prepared for these alternatives. That is the trade: the payload is cleaner but the receivers have to handle multiple value shapes. For the writing side, UCUM in Observation.valueQuantity: the strict version covers the strict pattern.
The valueCodeableConcept Pattern
For coded categorical results — "positive/negative", severity tiers — valueCodeableConcept with a proper coded value is the right choice. Not valueQuantity with a "positive/negative code."
That is what the FHIR value[x] polymorphism exists for. Use the correct shape.
The Storage Question
If your source system emits arbitrary units, you have two choices:
- Rewrite at ingestion to a FHIR-native shape
- Store the original arbitrary unit alongside a FHIR-clean shape
The second is safer if the source is authoritative. For the trade-off, storing quantities: original unit, canonical unit, or both covers it.
What Not To Do
- Do not invent a private UCUM extension — UCUM extension via curly-brace is standardized, private extensions are not
- Do not use
valueQuantitywith a made-up code — every consumer will treat it as UCUM - Do not silently drop the original unit when converting — you cannot roundtrip
Documenting Arbitrary Units
For any arbitrary unit you keep in your data model, document what it means, when it applies, and what the receiver should do with it. That documentation is what makes the alternative-value-shape choice defensible.
The Short Version
UCUM does not cover organizational buckets or non-dimensional counts. Curly-brace annotation handles annotated real units. Use valueInteger, valueString, or valueCodeableConcept for what UCUM cannot express. Never invent codes.

Sources
- UCUM canonical specification covering curly-brace - UCUM canonical specification covering curly-brace annotation grammar
