Build a terminology server on InterSystems IRIS for Health that:
- supports multiple terminologies through one architectural model
- currently exposes SNOMED CT and LOINC
- exposes both native and FHIR terminology APIs
- uses IRIS features such as interoperability, persistence, SQL and iFind in one integrated platform
- serves as a reference implementation for developers and partner conversations
This file explains how the repository is structured and why the architecture is shaped this way.
For setup steps, use docs/getting-started.md. For a narrative walkthrough, use docs/how-it-works.md. For contribution rules, use CONVENTIONS.md.
This repository is intentionally not built around one universal terminology schema.
Instead it uses:
- shared service contracts where there is a real common concept
- terminology-specific adapters where behavior diverges
- terminology-specific repositories where storage and query semantics diverge
- thin native and FHIR layers on top
That approach allows the server to expose one integrated view while still respecting the real complexity of SNOMED CT, LOINC and future terminologies.
IRIS for Health is part of the architecture, not just the runtime.
The repository takes advantage of IRIS for:
- production-based ingestion and operational orchestration
- persistent storage and SQL access
- integrated FHIR exposure
- iFind-backed search where that improves runtime query behavior
- one environment for load, build, query and API delivery
This is why the repository can present one terminology server instead of a loose collection of disconnected services.
The repository already contains a working multi-terminology server with:
- SNOMED CT ingestion, runtime structures and native/FHIR exposure
- LOINC ingestion, runtime structures and native/FHIR exposure
- a common service layer that routes supported terminology operations
- terminology-specific adapters and repositories underneath that common layer
Client
|
+--> Native terminology APIs
|
+--> FHIR terminology APIs
|
v
Terminology.Core.TermService
|
+--> SNOMED adapter -> SNOMED repository
|
+--> LOINC adapter -> LOINC repository
|
v
IRIS tables
Terminology release packages
|
v
IRIS production / file intake
|
+--> SNOMED load + build
|
+--> LOINC load + build
|
+--> ICD load + build
|
v
Terminology-specific source and runtime tables
Terminology.Fhir.InteractionsTerminology.Fhir.Operations.TerminologyOperations- operation-specific classes such as:
Terminology.Fhir.Operations.LookupOperationTerminology.Fhir.Operations.ValidateCodeOperationTerminology.Fhir.Operations.SubsumesOperationTerminology.Fhir.Operations.ExpandOperation
Terminology.Core.TermService
This path exposes one FHIR-oriented surface while routing behavior to the appropriate terminology implementation.
Terminology.Production.APITerminology.Production.BS.SnomedGatewayServiceTerminology.Production.BO.SnomedRepositoryOperationTerminology.Snomed.SnomedRepository
This path exposes SNOMED-specific native operations for search, lookup, hierarchy navigation, refsets and validation.
Terminology.Production.APITerminology.Production.BS.LoincGatewayServiceTerminology.Production.BO.LoincRepositoryOperationTerminology.Loinc.LoincRepository
This path exposes LOINC-specific native operations for search, lookup, displays, parts, hierarchy navigation, groups and validation.
Terminology.Snomed.SnomedAdapterTerminology.Loinc.LoincAdapter
These classes translate common terminology operations into terminology-specific repository behavior.
SNOMED:
Terminology.Production.BS.SnomedRf2FileServiceTerminology.Production.BP.SnomedRf2LoadTerminology.Snomed.Utils.LoaderRf2Terminology.Snomed.Utils.BuilderPreferredTermTerminology.Snomed.Utils.BuilderIsaClosure
LOINC:
Terminology.Production.BS.LoincFileServiceTerminology.Production.BP.LoincLoadTerminology.Loinc.Utils.LoaderTerminology.Loinc.Utils.BuilderDisplayTerminology.Loinc.Utils.BuilderHierarchy
Terminology.Core.TermService exists to define the integrated logical view of the server.
Responsibilities:
- expose shared terminology operations
- route requests to the correct adapter
- keep API and FHIR layers from hard-coding terminology-specific internals
Adapters exist because shared operations do not mean identical terminology behavior.
Responsibilities:
- translate shared operations into terminology-specific behavior
- preserve terminology-specific semantics when the common contract is too coarse to express them directly
- shield API and FHIR layers from storage and model details
Repositories exist because SQL and physical query behavior are still terminology-specific.
Responsibilities:
- contain SQL
- map rows into DTO/result shapes
- encode IRIS-specific query optimization choices such as iFind usage and ordering semantics
This separation is important. It lets the repo expose one server while still allowing each terminology to keep its own model, hierarchy behavior and runtime optimization strategy.
The physical model is intentionally terminology-specific where that makes sense.
Source tables:
Terminology_Snomed.ConceptTerminology_Snomed.DescriptionTerminology_Snomed.RelationshipTerminology_Snomed.RefsetMember
Derived tables:
Terminology_Snomed.PreferredTermTerminology_Snomed.PreferredTermStageTerminology_Snomed.IsaClosureTerminology_Snomed.LanguageRefSetConfig
Source/runtime tables:
Terminology_Loinc.CodeTerminology_Loinc.DisplayTerminology_Loinc.PartTerminology_Loinc.CodePartLinkTerminology_Loinc.HierarchyEdgeTerminology_Loinc.ClosureTerminology_Loinc.LoincGroupTerminology_Loinc.GroupMember
Source/runtime tables:
Terminology_ICD.ChapterTerminology_ICD.CodeTerminology_ICD.FamilyTerminology_ICD.HierarchyEdge
Shared metadata used by the integrated API/FHIR layers is stored separately in the core area, for example:
Terminology_Core.CodeSystemTerminology_Core.VersionRelease
The containerized environment watches input folders under iris/shared/.
Current examples:
- SNOMED packages under
iris/shared/in/snomed/ - LOINC packages under
iris/shared/in/loinc/ - ICD packages under
iris/shared/in/icd/
The IRIS production detects those files and starts the appropriate terminology load flow.
Each terminology is loaded using terminology-aware logic.
That is deliberate. The project does not pretend that SNOMED RF2 and LOINC package structures are the same.
After raw content is loaded, build steps create runtime-optimized structures such as:
- preferred-term structures
- display structures
- closure/hierarchy structures
These exist so the server does not have to reconstruct expensive query semantics on every request.
Once runtime structures exist:
- native terminology endpoints route through their terminology-specific operation and repository paths
- FHIR operations route through
Terminology.Core.TermService - adapters delegate execution to the correct terminology-specific repository
Responsibilities:
- parse requests
- validate request shape
- map results into native or FHIR responses
- call services
Must not:
- implement SQL
- know terminology table internals in detail
- duplicate business logic already owned by services or repositories
Responsibilities:
- define shared terminology operations
- route requests to the correct adapter
- keep cross-terminology contracts stable
Current example:
Terminology.Core.TermService
Responsibilities:
- implement terminology-specific behavior behind common contracts
- translate shared operations into terminology-specific repository calls
Current examples:
Terminology.Snomed.SnomedAdapterTerminology.Loinc.LoincAdapterTerminology.ICD.ICDAdapter
Responsibilities:
- contain SQL
- map rows into result shapes
- encode IRIS-specific query optimization
Current examples:
Terminology.Snomed.SnomedRepositoryTerminology.Loinc.LoincRepositoryTerminology.ICD.ICDRepository
Responsibilities:
- import external files
- load source content
- build optimized structures
- preserve release/version metadata
The repository already operates as a multi-terminology example, with SNOMED CT and LOINC implemented.
At the same time:
- physical models remain terminology-specific
- some native APIs are terminology-specific by design
- the common service surface is still intentionally narrow
The target is a hybrid model:
- one integrated logical service contract for shared terminology operations
- terminology-specific storage and behavior where needed
- additional adapters for future code systems instead of forcing one universal schema
Core terminology contracts
|
+--> SNOMED adapter
+--> LOINC adapter
+--> ICD adapter
+--> future terminology adapters
This avoids both extremes:
- forcing all terminologies into one physical model
- creating fully isolated implementations with no integrated service layer
The current SNOMED and LOINC implementations are the working base. Architectural changes should extend them, not flatten them.
The common service surface should stay narrow until at least two real terminology use cases justify expansion.
Current justified shared operations include:
- lookup
- validate-code
- subsumes
- search
- value set metadata and expansion support where already implemented
FHIR operations should depend on shared terminology services, not query terminology tables directly.
Future terminologies should plug in through the same service/adapter/repository pattern.
The intended package shape is:
Terminology.CoreTerminology.SnomedTerminology.LoincTerminology.FhirTerminology.Mapping
Within each area, keep responsibilities separated by:
- model
- service
- repository
- API
- load
- build
The terminology server includes a semantic vectorization layer to enable:
- free-text semantic search across terminologies
- semantic crosswalk between different code systems
The vectorization layer follows the same interoperability pattern:
REST API (/terminology/vector) | v VectorGatewayService (Business Service) | v VectorSearchOperation (Business Operation) | v Terminology.Vector.Utils | v Terminology_Vector.TermEmbedding
The vector store is implemented in:
Terminology_Vector.TermEmbedding
Main fields:
SystemUri→ canonical identifier of the terminologyReleaseId→ specific release/version of the terminologyCode→ terminology codeLang→ languageText→ textual representation used for embeddingModel→ embedding model usedEmbedding→ vector representation (HNSW indexed)
Unlike IRIS automatic embedding (EMBEDDING(...)), vectors are generated explicitly:
- using
sentence-transformersin embedded Python - batched processing (default batch size = 50)
- stored using
TO_VECTOR(..., DECIMAL) - indexed with HNSW for fast similarity search
Vectors are generated from:
- SNOMED →
Terminology_Snomed.PreferredTerm - LOINC →
Terminology_Loinc.Display - ICD/CIE →
Terminology_ICD.Code
The source is determined by:
ReleaseIdCodeSystem.Type(SNOMED, LOINC, ICD)
Free-text queries are vectorized and matched against stored embeddings:
VECTOR_DOT_PRODUCT(Embedding, query_vector)
Filtering is supported by:
- one or multiple
SystemUri - one or multiple
ReleaseId Lang
Cross-terminology mapping is achieved by:
- vectorizing a source concept (text or code)
- searching in target terminologies
- ranking results by similarity score
This provides:
- approximate equivalence suggestions
- multi-terminology exploration
- language-independent matching
Note: This is not a formal mapping, but a semantic similarity mechanism.
-
Terminology.Vector.Utils- vector generation
- batch insertion
- semantic search
- crosswalk logic
-
VectorGatewayService- entry point from REST
-
VectorSearchOperation- orchestration and delegation to Utils
- decouples vectorization from ingestion
- avoids runtime embedding computation
- supports multiple releases per terminology
- allows future replacement of embedding models
- FHIR
$translatebacked by vector similarity - hybrid search (text + vector)
- score threshold filtering
- precomputed crosswalk caches
Not required in the current stage:
- complete enterprise FHIR terminology parity
- authoring workflows
- one universal physical schema for every terminology
- promising future implementation directions before the current common contract is stable
Exploration areas may grow later, including additional search and discovery patterns on IRIS, but the current architectural focus remains the integrated multi-terminology server built on the existing IRIS capabilities.