FHIR Terminology Binding: CodeSystem, ValueSet, ConceptMap
Many coded FHIR elements carry a terminology binding to a ValueSet, but the constraint depends on the binding strength. A binding constrains or recommends values; it does not create one universal meaning by itself. A Coding is identified by system + code and, when the contract requires it, version; a CodeableConcept may contain multiple codings and text. VN Core v0.9.0 now publishes 165 CodeSystems, 168 ValueSets, 17 ConceptMaps, and 36 NamingSystems for Vietnamese healthcare use cases.
Audience: developers, vendors, regulators already comfortable with base FHIR who keep hitting "code not in valueset" errors or need to understand why terminology standardization is the make-or-break condition for interoperability.
TL;DR
- CodeSystem identifies a coding system and may publish content or a supplement; a Resource canonical is not necessarily the URI used in
Coding.system. - ValueSet describes selected values from one or more CodeSystems through includes, excludes, or enumerated codes and can then be used in a binding.
- ConceptMap records directional, context-specific relationships between codes or concepts—for example, a Vietnamese laboratory-index code to LOINC. It is not a whole-schema mapping from XML to FHIR Resources.
- NamingSystem registers URIs for identifiers (CCCD, BHYT card, BHXH number, hospital MRN), not for clinical codes.
- Binding strength has four levels:
required,extensible,preferred,example— they determine how tightly a ValueSet constrains a field.
On this page
- Four core concepts: CodeSystem, ValueSet, ConceptMap, NamingSystem
- Coding and CodeableConcept: the role of text
- Binding strength: required, extensible, preferred, example
- ValueSet — composition and expansion
- Operations: $expand, $validate-code, $lookup, $translate
- Terminology server: self-host or use a managed service
- VN Core terminology landscape — v0.9.0
- When to build your own CodeSystem versus reusing an international standard
- Frequently asked questions
- Further reading
1. Four core concepts
The FHIR Terminology Module (R4 §3.6) splits code-management resources into four buckets: CodeSystem defines the source-of-truth code set, ValueSet selects a usable subset, ConceptMap translates between coding systems, and NamingSystem registers identifier URIs. Understanding this division of labor is a prerequisite for reading any Implementation Guide — US Core, JP Core, or VN Core alike.
CodeSystem — the source-of-truth code set
A CodeSystem is the resource that defines exactly which codes exist and what each one means. Each CodeSystem owns a single globally unique canonical URL that identifies the code set. VN Core uses the convention http://fhir.hl7.org.vn/core/CodeSystem/ with a -cs suffix — for example vn-ethnicity-cs for the catalog of 54 Vietnamese ethnic groups, or vn-icd10-cs for the Vietnamese edition of ICD-10.
{
"resourceType": "CodeSystem",
"url": "http://fhir.hl7.org.vn/core/CodeSystem/vn-ethnicity-cs",
"version": "1.0.0",
"name": "VNEthnicity",
"title": "Dân tộc Việt Nam",
"status": "active",
"content": "complete",
"concept": [
{ "code": "01", "display": "Kinh" },
{ "code": "02", "display": "Tày" },
{ "code": "03", "display": "Thái" }
]
}
The content field signals how complete the resource is: complete (every code is included in the resource), fragment (only part of the system), example (illustrative only), or not-present (only the metadata is defined and the codes live elsewhere — appropriate for very large code sets like SNOMED CT).
ValueSet — the usable subset
A ValueSet introduces no new codes; it carves out a subset of one or more CodeSystems for binding to a field. A single CodeSystem can spawn many different ValueSets depending on context. ICD-10 VN, for example, contains more than 14,000 codes, but a ValueSet for pediatric diagnoses or a ValueSet for communicable diseases will pick just a few hundred relevant codes.
{
"resourceType": "ValueSet",
"url": "http://fhir.hl7.org.vn/core/ValueSet/vn-ethnicity-vs",
"version": "1.0.0",
"name": "VNEthnicityVS",
"status": "active",
"compose": {
"include": [
{
"system": "http://fhir.hl7.org.vn/core/CodeSystem/vn-ethnicity-cs"
}
]
}
}
Note that FHIR R4 makes the status field mandatory (cardinality 1..1) for CodeSystem, ValueSet, ConceptMap, and NamingSystem alike. Forgetting status trips a validator error immediately.
ConceptMap — mapping between two systems
A ConceptMap describes relationships between codes in two systems. Appropriate Vietnamese use cases include mapping ICD-10 VN to the applicable ICD-10 WHO edition or Vietnamese laboratory-index codes to LOINC. Transforming KCB output XML fields and structure into Claim, Coverage, or ExplanationOfBenefit requires a governed, tested structural mapping specification or adapter; ConceptMap applies only to coded fields. In R4, sourceUri and targetUri describe the scope of the mapping (typically a ValueSet URL), while group.source and group.target hold the specific CodeSystem URLs.
{
"resourceType": "ConceptMap",
"url": "http://fhir.hl7.org.vn/core/ConceptMap/vn-icd10-to-who",
"version": "1.0.0",
"name": "VNICD10ToWHO",
"status": "active",
"sourceUri": "http://fhir.hl7.org.vn/core/ValueSet/vn-icd10-vs",
"targetUri": "http://hl7.org/fhir/ValueSet/icd-10",
"group": [
{
"source": "http://fhir.hl7.org.vn/core/CodeSystem/vn-icd10-cs",
"target": "http://hl7.org/fhir/sid/icd-10",
"element": [
{
"code": "I10.0",
"target": [
{ "code": "I10", "equivalence": "wider" }
]
}
]
}
]
}
The equivalence field accepts values such as equal, equivalent, wider, narrower, inexact, and unmatched, capturing the degree of semantic equivalence rather than collapsing every relationship into a one-to-one match.
NamingSystem — registering identifier URIs
NamingSystem differs from the other three resources: it does not manage clinical codes but instead registers URIs for identifier systems. The national ID card (CCCD), BHYT card number, BHXH number, and hospital MRN are all identifier systems, and each requires a unique URI so that Patient.identifier can point to it.
{
"resourceType": "NamingSystem",
"name": "VNCCCD",
"status": "active",
"kind": "identifier",
"date": "2026-04-30",
"uniqueId": [
{
"type": "uri",
"value": "http://fhir.hl7.org.vn/core/sid/cccd",
"preferred": true
}
]
}
VN Core's convention is http://fhir.hl7.org.vn/core/sid/{cccd|bhyt|bhxh|gks|passport}. Note that NamingSystem also requires both status and date.
2. Coding and CodeableConcept
These two datatypes cause the most confusion for newcomers to FHIR. Coding represents a single code with system, version, code, and display. CodeableConcept wraps an array of equivalent Coding entries together with a free-text text field that captures the human-readable description.
"code": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/icd-10",
"version": "2019",
"code": "I10",
"display": "Essential hypertension"
},
{
"system": "http://fhir.hl7.org.vn/core/CodeSystem/vn-icd10-cs",
"code": "I10.0",
"display": "Tăng huyết áp vô căn"
}
],
"text": "Tăng huyết áp"
}
The same diagnosis may be coded in parallel when the Coding entries genuinely express the same concept. CodeableConcept.text is optional in base FHIR; a profile or IG may require or recommend it to retain the author's wording. Text supports human interpretation but does not replace the code, system, version, display, and provenance needed for machine processing.
Pragmatic rule: use CodeableConcept where the element permits it and both coding and author wording are needed. Preserve text where clinically useful and govern coding versions; neither is a universal substitute for the other.
3. Binding strength: four levels of constraint
When a FHIR field is bound to a ValueSet, implementers need to know how strictly the binding applies. HL7 R4 defines four levels on the Terminology — Binding page (hl7.org/fhir/R4/terminologies.html#strength):
| Strength | Meaning | FHIR R4 base example |
|---|---|---|
required | The code must come from the ValueSet. Validators flag anything outside it as an error. Text-only is not allowed. | Patient.gender bound to AdministrativeGender (male/female/other/unknown). |
extensible | If the concept is already in the ValueSet, you must use that code. You may extend with codes outside the set only when no listed concept covers what you need to record. | Patient.maritalStatus is bound extensible to MaritalStatus. Downstream profiles may tighten this further. |
preferred | Using the ValueSet is recommended but not required. Validators only emit a warning. | Encounter.serviceType is bound preferred to ServiceType. |
example | The ValueSet is purely illustrative. There is no binding obligation at all. | Condition.code in R4 base is bound example to Condition/Problem/Diagnosis Codes. |
A profile such as VN Core is free to tighten the binding strength inherited from base. Where R4 base binds Condition.code at example strength, VN Core may re-profile it to extensible against an ICD-10 VN ValueSet, forcing systems to prefer ICD-10 VN codes whenever a suitable one exists.
Important: extensible is stricter than preferred. If the concept that needs to be recorded does appear in the ValueSet but the user fills in a different code or only text, the validator raises an error. preferred is purely advisory — there is no enforcement mechanism behind it.
4. ValueSet — composition and expansion
ValueSets have two faces: composition (the rules for selection) and expansion (the resulting flat list of actual codes).
Composition — the definition
The compose section of a ValueSet lists the rules for picking codes: include selects sets, exclude removes them. Selection can be driven by filter on CodeSystem properties — for example all descendants of a parent code, or all codes with status = active.
ValueSet: VNEncounterTypeVS
Id: vn-encounter-type-vs
Title: "Loại lượt khám"
Description: "Phân loại lượt khám theo TT 13/2025/TT-BYT"
* ^status = #active
* include codes from system VNEncounterTypeCS where status = #active Expansion — the result
When a terminology server expands a ValueSet (via the $expand operation), the result is a flat list of actual codes:
{
"resourceType": "ValueSet",
"url": "http://fhir.hl7.org.vn/core/ValueSet/vn-encounter-type-vs",
"status": "active",
"expansion": {
"timestamp": "2026-04-30T10:00:00+07:00",
"contains": [
{ "system": "http://fhir.hl7.org.vn/core/CodeSystem/vn-encounter-type-cs", "code": "OUTPATIENT", "display": "Ngoại trú" },
{ "system": "http://fhir.hl7.org.vn/core/CodeSystem/vn-encounter-type-cs", "code": "INPATIENT", "display": "Nội trú" },
{ "system": "http://fhir.hl7.org.vn/core/CodeSystem/vn-encounter-type-cs", "code": "EMERGENCY", "display": "Cấp cứu" }
]
}
} Composition defines the selection rules, while expansion is a result produced at a point in time with specific terminology versions and parameters. If the composition does not pin a version, a recomputed expansion may change with the CodeSystem. Production systems should therefore retain expansion version, timestamp, and parameters rather than assume newly included codes are automatically safe to use.
5. Operations: $expand, $validate-code, $lookup, $translate, $subsumes
FHIR specifies the commonly used terminology operations below. Support for each operation, parameter, language, paging mode, and code system must be advertised in the server's CapabilityStatement and tested; not every terminology server supports all of them:
$expandon ValueSet — returns the flat list of codes. Supports filtering, paging, and language selection.$validate-codeon ValueSet or CodeSystem — checks whether a given code is valid in the requested context.$lookupon CodeSystem — retrieves the display value, multilingual designations, and properties of a code.$translateon ConceptMap — applies a mapping to translate a code from one system to another.$subsumeson CodeSystem — tests the parent-child (subsumption) relationship between two codes.
GET /ValueSet/vn-ethnicity-vs/$expand
GET /CodeSystem/vn-icd10-cs/$lookup?code=I10.0
GET /CodeSystem/vn-icd10-cs/$validate-code?code=I10.0
POST /ConceptMap/vn-icd10-to-who/$translate?code=I10.0&system=http://fhir.hl7.org.vn/core/CodeSystem/vn-icd10-cs
An implementation may use $expand to populate a picker, $validate-code at data entry or a validation gate, and $translate where a governed ConceptMap exists. Call frequency, caching, outage behavior, and equivalence checks belong in the SLA and architecture; a $translate result is not automatically an equivalent mapping or a valid BHXH submission code.
6. Terminology server
A terminology server is the dedicated service that handles those operations. The most common options:
- Ontoserver (CSIRO, Australia) — a mature commercial product, strong on SNOMED CT, used in AU Core and the NHS.
- HAPI FHIR JPA Server — open source, ships with a complete terminology module, well suited for in-country deployments.
- Snowstorm (SNOMED International) — open source, purpose-built for SNOMED CT.
- tx.fhir.org — the public terminology server operated by HL7, used for testing and IG validation.
Choosing a public or self-hosted terminology service requires analysis of request data, terminology licensing, SLA, threat model, and cross-border transfers. Patient data or sensitive context should not be sent to a public service merely to validate a code. Cybersecurity and personal-data law should not be read as a blanket requirement that every terminology server be hosted in Vietnam; each implementer must assess the applicable scope.
7. VN Core terminology landscape
The VN Core terminology stack combines reused international standards with Vietnam-specific CodeSystems. Codes derived from legal instruments should retain citation and provenance to the relevant instrument and annex; international terminology should retain its system, version, publisher, and licensing conditions. A Vietnamese legal citation must not be fabricated for every international code.
| Code set | CodeSystem ID | Scope in v0.9.0 | Vietnam legal reference |
|---|---|---|---|
| ICD-10 VN | vn-icd10-cs | content = not-present; metadata points to the governed source | Decision 4469/QĐ-BYT and additions recorded in the artifact |
| ICD-9-CM 2026 | vn-icd9-cm-cs | 3,882 codes in v0.9.0 | Decision 387/QĐ-BYT (05/02/2026) |
| Ethnicity | vn-ethnicity-cs | 56 codes: 54 ethnic groups, foreign person, and unknown | Statistical catalogue with provenance recorded in the artifact |
| Current administrative divisions | vn-province-cs, vn-ward-cs | 34 provinces/cities and 3,321 communes, wards, or special zones | Resolution 202/2025/QH15 and Decision 19/2025/QĐ-TTg |
| Paraclinical indicators | vn-cls-cs | 2,964 source codes; the LOINC ConceptMap requires equivalence review | Decision 1227/QĐ-BYT (11/04/2025) |
| LOINC Vietnamese supplement | vn-loinc-cs | CodeSystem supplement to http://loinc.org; its URL is not a Coding.system | LOINC 2.78 in package v0.9.0; the current LOINC release is tracked separately |
| SNOMED CT Vietnamese supplement | vn-snomed-subset-cs | Supplement for 76,066 unique SCTIDs; coding still uses http://snomed.info/sct | Decisions 2427, 2493, and 2805/QĐ-BYT; SNOMED CT licence terms still apply |
| Legal-document reference list | vn-legal-document-ref-cs | 172 concepts in v0.9.0 | Project-compiled registry; each instrument's status is governed separately |
Relationships between ICD-10 VN and the WHO edition must be assessed per code and version; not every detailed code can be inferred to have a wider relationship. A ConceptMap should declare source and target versions and equivalence per mapping, while retaining the source code where validation is incomplete.
SNOMED CT has separate licensing conditions. Decisions 2427, 2493, and 2805 define Vietnamese mapping or terminology scope but should not be treated as a licence to distribute the complete international edition. Implementers must check current SNOMED International/MLDS terms for their territory and use case.
8. When to build your own CodeSystem
A common mistake in greenfield projects is to mint a custom CodeSystem for everything, which fragments terminology and destroys interoperability. The HL7 Vocabulary Working Group's general rule:
Do not roll your own when
- A suitable international standard already exists (ICD-10, LOINC, SNOMED CT, ATC, ISO 3166).
- FHIR core or terminology.hl7.org already covers the concept (AdministrativeGender, MaritalStatus, ContactPointSystem).
- A strong regional IG (US Core, JP Core) already defines a reusable CodeSystem.
Do build your own when
- The concept is Vietnam-specific: 54 ethnic groups, BHYT subject categories, care tiers under Resolution 202/2025, hospital ranks per Circular 06/2024.
- A specific Vietnamese legal instrument issues a code list (Ministry of Health Decision, Ministry of Health Circular, General Statistics Office Decision).
- The international code set lacks granular branches that Vietnamese practice requires (for example, ICD-10 VN expanding beyond ICD-10 WHO).
- You need a CodeSystem internal to the IG (for example,
VNLegalDocumentRefCSfor citing legal documents from profiles and extensions).
Once you commit to building your own, three hard rules apply:
- Codes derived from a statutory catalogue must trace to the source instrument or annex; international and internal governance codes require provenance and a namespace appropriate to their actual source.
- Versioning must be explicit: when the underlying legal instrument changes, increment the CodeSystem version and mark superseded codes with
status = deprecatedor aretirement-date. - The canonical URL pattern
http://fhir.hl7.org.vn/core/CodeSystem/vn-{domain}-csis immutable.
9. Frequently asked questions
Can a single field be bound to several ValueSets at once?
FHIR R4 allows only one primary binding per element. However, because CodeableConcept.coding is an array, a single field can carry multiple Coding entries from different CodeSystems, as long as they all express the same concept. This is the standard mechanism for coding a Condition.code with both ICD-10 VN and SNOMED CT simultaneously.
Where does ICD-10 VN diverge from ICD-10 WHO?
ICD-10 VN was issued under Decision 4469/QĐ-BYT and includes additions such as the COVID-19 codes under Decision 98/QĐ-BYT. Its relationship to a WHO edition must be checked by code, version, and ConceptMap; do not assume that every three-character code is equivalent or that divergence occurs only at one fixed level.
Is a SNOMED CT license mandatory?
Vietnam was not listed as a SNOMED International member on the membership list reviewed on 01 June 2026. Rights and fees in non-member territories depend on the use case, territory, and available exemptions; an organization should check the current SNOMED International/MLDS terms before downloading, deploying, or distributing content. Decisions 2427, 2493, and 2805 provide Vietnamese mapping/terminology scope and should not be treated as a licence to distribute the full SNOMED CT edition.
Can NamingSystem stand in for CodeSystem?
No. NamingSystem only registers URIs for identifier systems (CCCD, BHYT, BHXH, MRN); it does not manage clinical codes. Conflating the two is a common source of validator errors: Patient.identifier.system must be a URI registered through a NamingSystem, while Condition.code.coding.system must point to the canonical URL of a CodeSystem.
References
- HL7 FHIR R4 — Terminology Module: hl7.org/fhir/R4/terminology-module.html
- HL7 FHIR R4 — Binding strength: hl7.org/fhir/R4/terminologies.html#strength
- HL7 FHIR R4 — CodeSystem definitions: hl7.org/fhir/R4/codesystem-definitions.html
- HL7 FHIR R4 — ValueSet definitions: hl7.org/fhir/R4/valueset-definitions.html
- HL7 FHIR R4 — ConceptMap definitions: hl7.org/fhir/R4/conceptmap-definitions.html
- HL7 FHIR R4 — NamingSystem definitions: hl7.org/fhir/R4/namingsystem-definitions.html
- Decision 4469/QĐ-BYT (28/10/2020) — Vietnamese edition of ICD-10.
- Decision 98/QĐ-BYT (14/01/2022) — Adding COVID-19 codes to ICD-10 VN.
- Decision 1227/QĐ-BYT (11/04/2025) — Paraclinical indicator code list, batch 1 (LOINC mapping).
- Decision 2427/QĐ-BYT (25/07/2025) — SNOMED CT VN batch 1, Body Structure.
- Decision 2493/QĐ-BYT (08/2025) — SNOMED CT VN batch 2, Morphologic Abnormality.
- Decision 2805/QĐ-BYT (04/09/2025) — SNOMED CT VN batch 3, Allergy and Finding.
- Decision 387/QĐ-BYT (05/02/2026) — ICD-9-CM 2026 classification.
- Resolution 202/2025/QH15 (12/06/2025) — Reorganization of provincial-level administrative units.
- Circular 06/2024/TT-BYT (16/05/2024) — Healthcare facility ranks (4 tiers).
- Snowstorm SNOMED CT terminology server: github.com/IHTSDO/snowstorm
- Ontoserver (CSIRO): ontoserver.csiro.au