Healthcare Terminology Services: SNOMED, LOINC, ICD-10, and RxNorm Mapping
Interoperability

Healthcare Terminology Services: SNOMED, LOINC, ICD-10, and RxNorm Mapping

Abhinav Mohite
FHIR Subject Matter Expert, Mindbowser
TL;DR
  • Four code systems do four different jobs inside a FHIR record: LOINC identifies lab tests and measurements, SNOMED CT codes clinical findings and diagnoses, ICD-10-CM handles billing and regulatory reporting, and RxNorm identifies medications.
  • Each is governed and released by a different body on a different cadence: Regenstrief Institute (LOINC, semiannual through 2026, moving to monthly in 2027), SNOMED International (SNOMED CT, rolling releases roughly monthly), NLM (RxNorm, monthly full release plus weekly updates), and CMS/NCHS (ICD-10-CM, annual, with the FY2027 update effective October 1, 2026).
  • FHIR represents all of this through three resource types, CodeSystem, ValueSet, and ConceptMap, and the operation that actually maps a code from one system to another is $translate. In practice, the mapping ambiguity between these systems costs more project time than the FHIR mechanics ever do.

A lab result, a diagnosis, and a medication order all speak different coded languages inside a FHIR system. LOINC identifies the lab test. SNOMED CT or ICD-10 codes the diagnosis. RxNorm identifies the medication. Get the mapping between them wrong and you don’t get an error, you get a database full of technically-valid nonsense: records that pass every schema check and still can’t be compared, aggregated, or trusted.

I scope integration projects that touch two, sometimes ten, source systems at once, and the terminology layer is where estimates go wrong, not the transport layer. This is a mapping-discipline problem, not a naming-trivia problem, and it deserves to be treated like one.

The Four Code Systems, and Why FHIR Needs All of Them

Healthcare terminology code system comparison
Fig 1: Comparing Clinical Terminology System Purposes

FHIR doesn’t invent its own vocabulary for clinical concepts. It’s a wrapper, a way to structure data, and the actual meaning of a lab result, a diagnosis, or a medication comes from an external code system FHIR references. I still run into teams that treat FHIR itself as the vocabulary, and that’s the first assumption I correct on a new engagement.

  • LOINC identifies observations and measurements: lab tests, vital signs, clinical panels. The question it answers is “what was measured.”
  • SNOMED CT identifies clinical concepts: findings, diagnoses, procedures, body structures. The question it answers is “what was found or done.”
  • ICD-10, specifically ICD-10-CM in the US, identifies diagnoses for billing and reporting. It’s a narrower, classification-style system, not a full clinical vocabulary.
  • RxNorm identifies medications: a normalized layer that ties together brand names, generics, and dose forms under one identifier.

None of these four overlaps cleanly with another. SNOMED CT and ICD-10 both touch diagnoses, but SNOMED is a clinical vocabulary, many-to-many and granular, while ICD-10 is a billing classification, coarser and built for reimbursement. The mapping between them is one-directional-ish and lossy, not a clean swap. And that distinction, more than any FHIR mechanic, is the reason the rest of this page exists.

This distinction matters before you touch FHIR at all: pick the wrong code system for a field, and no amount of correct FHIR structure fixes it downstream.

LOINC: Identifying Lab Tests and Results

Clinical code system release schedules
Fig 2: Healthcare Coding Standards and Release Schedules

LOINC answers one question: what exactly was measured. Not the result value, the identity of the test itself. I think of it as the identity layer for a measurement, not the value it produced.

It’s governed by the Regenstrief Institute’s Health Data Standards Unit. The current version is LOINC 2.82, released February 24, 2026, alongside RELMA 7.15 (the mapping and search tool) on the same date. Regenstrief has run a semiannual release cadence, February and August, through 2026, and has announced a shift to monthly releases starting in 2027.

A LOINC code identifies a specific test or measurement, a potassium serum level, for example, independent of how any given lab performs or reports it. That’s what makes cross-lab data comparable. Recent LOINC expansion has covered molecular genetics, microbiology, toxicology, multi-gene diagnostic panels, plus new visual-field and GI-endoscopic testing concepts, per the 2.82 release notes. I’ve had to onboard panels like those into a mapping table more than once this year.

If you’re building an interface that pulls lab results from more than one LIS, the LOINC code is what lets you treat “Potassium, Serum” from two different lab systems as the same data point. Without it, you’re matching on free-text test names, which never holds up across vendors; one lab calls it “K, Serum,” another calls it “Potassium Level,” and a string match breaks on the first vendor update.

I’ve watched exactly that kind of free-text match pass QA on day one and quietly start dropping records six months later when a vendor renamed a handful of tests.

SNOMED CT: Coding Clinical Findings and Diagnoses

SNOMED CT is the closest thing healthcare has to a full clinical vocabulary, and that scope is exactly what makes mapping it to anything else hard.

It’s governed by SNOMED International, not a US-specific body, which releases the International Edition on a rolling cadence, with multiple editions confirmed through 2026 in June, August, and September. US distribution runs through the National Library of Medicine as the US SNOMED International member, the “US Edition” layer on top of the International Edition. I keep that distinction straight because vendors don’t always make it obvious which edition they’ve loaded.

SNOMED CT is a full clinical ontology: concepts for findings, diagnoses, procedures, body structures, and organisms, related to each other hierarchically rather than sitting in a flat code list. That hierarchy is why one SNOMED concept can be more specific than the ICD-10 code it maps to, or map to multiple ICD-10 codes depending on context. The two systems simply aren’t structured the same way underneath, and I’ve seen that structural gap get mistaken for a data-quality bug more than once.

Inside FHIR, SNOMED CT is the default code system for Condition.code, Observation.valueCodeableConcept, and most clinical-finding fields in US Core profiles. If you’re working in FHIR architecture built on US Core, you’re already leaning on SNOMED CT more than you realize. But most teams don’t notice until they try to map that clinical data somewhere SNOMED CT isn’t the native vocabulary.

ICD-10: Billing and Regulatory Reporting

ICD-10 gets confused with SNOMED CT constantly, and I still get asked to explain the difference on almost every FHIR-adjacent billing conversation. The confusion is understandable; both code diagnoses. They exist for different jobs.

Base ICD-10 is maintained internationally by the World Health Organization. The US uses a clinical modification, ICD-10-CM, maintained by CMS and NCHS specifically for billing and regulatory reporting. ICD-10-CM updates annually, effective October 1 each year, and the FY2027 update is effective October 1, 2026: 190 new codes, 30 deleted, 4 revised, released by CMS in June 2026 for the October 2026 through September 2027 usage window.

Structurally, ICD-10-CM is coarser than SNOMED CT by design. It’s a classification system built to group diagnoses into reimbursable, reportable categories, not to capture full clinical nuance. A single ICD-10-CM code corresponds to multiple distinct SNOMED CT concepts collapsed together, and that collapse is a real source of information loss when systems map SNOMED-coded clinical data down to ICD-10 for billing.

Actually, I think “loss” undersells it: it’s not that detail disappears, it’s that it becomes unrecoverable once collapsed, you can’t reconstruct the original SNOMED concept from the ICD-10 code alone.

In FHIR, ICD-10-CM shows up behind claims and billing-oriented resources, Claim, ExplanationOfBenefit, while SNOMED CT covers the clinical side. The two systems coexist in the same patient record for entirely different purposes, and treating them as interchangeable is where I see a lot of mapping projects start losing accuracy.

Struggling with Inconsistent Clinical Data Across EHRs?

RxNorm: Normalizing Medication Data

A single medication can show up under a dozen different names across systems: brand name, generic name, NDC code, a pharmacy vendor’s internal ID. RxNorm exists to collapse all of that into one identifier.

It’s governed by the National Library of Medicine, part of the Unified Medical Language System (UMLS). The full RxNorm dataset releases on the first Monday of every month, with weekly incremental updates in between, and the RxNorm API, via RxNav, updates monthly following each full release. RxNorm is non-proprietary: no license is required to use RxNorm data or the RxNorm API, which isn’t true of every UMLS-linked vocabulary.

Structurally, RxNorm normalizes a drug’s active ingredient, strength, and dose form into a single concept, an RxCUI, then links that concept out to the various drug vocabularies (NDC, First Databank, Multum, and others) that pharmacy and e-prescribing systems actually use day to day. I treat the RxCUI as the one identifier worth anchoring a medication record to, everything else downstream is a lookup off of it.

But an e-prescribing integration that doesn’t normalize through RxNorm ends up comparing NDC codes from two different pharmacy systems directly, which breaks the moment either vendor updates their internal packaging codes. RxNorm is the layer that keeps the comparison stable, and it’s what lets a drug-interaction check or an e-prescribing system compare medications that entered the record through completely different source systems. I’ve never seen a pharmacy integration skip RxNorm and hold up over time.

How FHIR Represents and Maps Terminology

FHIR CodeSystem ValueSet ConceptMap operations
Fig 3: Understanding FHIR Terminology Resource Relationships

All four code systems above are external to FHIR. FHIR’s job is to reference them consistently, and three resource types plus three operations do that work.

  • CodeSystem defines or describes a code system itself. SNOMED CT, LOINC, and the others can each be represented as a CodeSystem resource, or referenced by canonical URL without fully importing it.
  • ValueSet is a constrained, usable subset of codes from one or more CodeSystems, scoped to a specific context, for example, the acceptable diagnosis codes for a given form field.
  • ConceptMap defines an actual mapping between codes in two different systems, SNOMED CT to ICD-10, for example.
  • $lookup retrieves full metadata, display name, definition, properties, for a single code from a CodeSystem.
  • $expand generates the actual list of codes that belong to a ValueSet definition, used to populate a picker or dropdown with current, valid codes.
  • $translate does the real mapping work: it takes a code from one system and, using a ConceptMap, returns the equivalent code, or codes, mappings aren’t always 1:1, in a target system.

I’ve hit $expand timeouts against a ValueSet with more than 40,000 codes more than once. The operation is defined generically enough that server-side performance varies wildly between FHIR servers, and it’s the choice between $lookup (one code) and $expand (a whole set) that decides whether a terminology check runs in milliseconds or minutes. I check the ValueSet size before I pick which operation to use, that single habit has saved more debugging time than anything else in this section.

I default to $lookup wherever a form only needs to validate a single submitted code, and save $expand for the cases that actually need a full picker list.

But this connects to a related mechanic worth calling out: FHIR bulk data export filters a large export by resource type using _type. $translate and $expand do something structurally similar at the code level, narrowing down to exactly the codes a given context needs, rather than the resource types. Same underlying idea, applied one layer deeper. For more on how these mechanics fit into a broader integration build, see the guide to FHIR implementation patterns.

Where Terminology Mapping Actually Breaks

Clinical terminology mapping failure scenarios
Fig 4: Common Challenges in Clinical Code Mapping

The FHIR mechanics in the last section are straightforward. What isn’t straightforward is the mapping data itself, and that’s where terminology projects actually lose time.

Non-1:1 mappings are the default, not the exception. A single SNOMED CT concept can legitimately map to multiple ICD-10-CM codes depending on clinical context, laterality, severity, encounter type, and a ConceptMap has to encode that ambiguity, not resolve it away.

Version drift between systems breaks mappings silently. SNOMED CT updates roughly monthly; ICD-10-CM updates once a year. A ConceptMap built against last year’s SNOMED release can reference a code that’s since been retired or split, and nothing errors, the mapping just quietly stops matching.

Two EHRs rarely use identical subsets, either. Even when both systems nominally use SNOMED CT, each vendor ships its own curated ValueSet. Epic’s picker list and Cerner’s picker list for the same clinical concept aren’t guaranteed to contain the same codes, and that mismatch is invisible until someone tries to reconcile the two.

In multi-standard integration work I’ve scoped, pulling structured clinical and financial data out of Epic via HL7 and FHIR for downstream matching, the terminology layer, not the transport layer, was consistently where the actual mapping effort went. That’s adjacent proof, a financial-assistance matching platform integration, not a direct claim about terminology-mapping specifically, but the pattern held: getting the data to move was the easy part.

Healthcare terminology mapping integration architecture
Fig 5: Multi-System Healthcare Terminology Integration Architecture

And teams doing HL7 v2 to FHIR mapping will recognize this same problem from the other direction: v2 tables carry their own code sets, and they drift against version updates the same way. I’d budget for that drift the same way I budget for SNOMED/ICD-10 drift, on a recurring schedule, not a one-time mapping sprint.

Building Terminology Mapping Into a Multi-System FHIR Build

A single-system implementation, one EHR, one code system, one ValueSet, doesn’t need an accelerator. The FHIR terminology-service spec is enough on its own. I wouldn’t recommend one for that case, it’s added complexity with nothing to offset it.

The complexity scales with the number of source systems, not the number of code systems. Two EHRs across four code systems is a manageable mapping table. Ten source systems, EHRs, LIS vendors, pharmacy systems, each with their own ValueSet curation, is a maintenance problem, not a one-time mapping exercise.

Version drift means terminology mapping isn’t a build-once task. It needs an ongoing process tied to each code system’s release cadence: LOINC semiannual then monthly, SNOMED CT rolling, RxNorm monthly, ICD-10-CM annual. A mapping table that’s correct on go-live day can be quietly wrong six months later if nobody’s watching the release calendars.

At that scale, ConnectHealth handles the multi-EHR terminology-normalization layer: one consistent mapping surface across Cerner, Epic, Athena, and Meditech instead of hand-maintaining a separate ConceptMap per connection. The honest version of this framing carries through either way: single-system builds don’t need this, multi-system, multi-vendor builds are where the accelerator earns its place.

If you’re building this at platform scale, I’d start with the healthcare interoperability solutions work and the EHR integration capability behind it.

Frequently Asked Questions

LOINC identifies lab tests and clinical measurements, answering “what was measured” independent of how any individual lab performs or reports the test. It’s governed by Regenstrief Institute and lets systems compare lab results across different source labs consistently.

SNOMED CT is a full clinical vocabulary that codes findings, diagnoses, procedures, and body structures. It’s governed by SNOMED International and is the default terminology for clinical-finding fields in FHIR US Core profiles.

No. SNOMED CT is a granular clinical vocabulary used for documenting findings and diagnoses. ICD-10-CM is a coarser billing and regulatory classification maintained by CMS and NCHS. A single ICD-10-CM code represents multiple distinct SNOMED CT concepts collapsed together.

FHIR uses three resource types, CodeSystem, ValueSet, and ConceptMap, to represent terminology, and the $translate operation to actually map a code from one system to another using a ConceptMap. $lookup retrieves metadata for a single code, and $expand generates the full list of codes in a ValueSet.

Abhinav Mohite

Abhinav Mohite

FHIR Subject Matter Expert, Mindbowser

Connect Now

Abhinav Mohite is a FHIR Subject Matter Expert at Mindbowser. He has 6+ years of experience in US healthcare interoperability, with deep expertise in HL7, FHIR, and SMART on FHIR implementation.

A Business Analyst and Product Owner hybrid with strong Agile and SDLC fluency, Abhinav bridges the gap between clinical workflow reality and technical protocol, making him a go-to expert for EHR integration projects where standards meet real-world delivery.

Share This Blog

Read More Similar Blogs

Let’s #Transform Healthcare,# Together.

Partner with us to design, build, and scale digital solutions that drive better outcomes.

Location

Global Tech Teams LLC, 525 Washington Blvd, Industrious at Newport Tower, Jersey City, NJ 07310, United States.

Contact

+1 408 786 5974
contact@mindbowser.com
BOOK A QUICK CONSULTATION

Have a Healthcare Project in Mind?

Let’s discuss your goals, workflows, and next steps in a focused consultation call.

Calendar icon Schedule a Call

Contact form