Skip to main content

Terminology Service — Deployment Topology

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services · 02 DDD

1. Runtime

AttributeValue
RuntimeNestJS 11 / Node.js 22
LanguageTypeScript 5.x
ContainerDocker (linux/amd64 + linux/arm64)
OrchestrationKubernetes (production), Docker Compose (local dev)
Base imagenode:22-alpine

2. Kubernetes Deployment

ParameterValue
Namespaceehealth-platform
Deployment nameterminology-service
Min replicas2
Max replicas6 (HPA on CPU + request rate)
CPU request / limit500m / 2000m (bulk import queries are CPU-intensive)
Memory request / limit512Mi / 1Gi
Pod disruption budgetmin 1 available
Rollout strategyRollingUpdate — maxUnavailable 1, maxSurge 1

3. Networking

ConcernConfig
Internal addressterminology-service.ehealth-platform.svc.cluster.local:3000
FHIR pathGET /fhir/R4/CodeSystem/$lookup, etc. — exposed via Kong for external FHIR clients
Internal API/internal/terminology/* — cluster-internal only (no Kong exposure)
Health checkGET /health — liveness + readiness (includes DB + Redis dependency check)
TLSTerminated at Kong for external; mTLS in cluster mesh (Linkerd)

4. Dependencies (Runtime)

DependencyTypeNotes
PostgreSQL 16Primary storeConcepts, drug data, value sets (non-PHI; global region or AFG)
Redis 7CacheHot concept lookups, TTL 1h for lookups/validate, 5 min for value set expansions
NATS JetStreamEvent busOutbox relay for concept mutation events
KeycloakAuthJWT validation for /v1/terminology/* and /fhir/R4/*
KongIngressExternal FHIR operation exposure

No outbound service-to-service calls. Terminology-service is a leaf node in the dependency graph.


5. ETL Pipeline (Offline Data Load)

Licensed terminology data is loaded via the ETL pipeline at deployment time. The ETL runs as a Kubernetes Job (not part of the running service):

kubernetes/jobs/terminology-etl/
├── loinc-import.job.yaml
├── snomed-import.job.yaml
├── rxnorm-import.job.yaml
├── icd10-import.job.yaml

ETL jobs read from licensed data files in a secure object storage bucket (not committed to the repository). The service's POST /internal/terminology/import endpoint is used by the ETL and is disabled in production unless IMPORT_ENABLED=true.


6. Scaling Triggers

MetricScale-out threshold
CPU utilization> 65% for 2 min (bulk import elevates CPU)
Request rate (RPM)> 1000 RPM per pod
Memory utilization> 80% for 5 min

7. Environment Variables

VariableDescription
DATABASE_URLPostgreSQL connection string
REDIS_URLRedis connection string
NATS_URLNATS JetStream URL
KEYCLOAK_REALM_URLKeycloak issuer URL
INTERNAL_TOKENOptional shared secret for /internal/* routes
IMPORT_ENABLEDtrue to enable CSV import endpoint (default: false)
CACHE_TTL_LOOKUP_SECONDSDefault 3600
CACHE_TTL_EXPAND_SECONDSDefault 300
MAX_EXPANSION_SIZEMax concepts returned per ValueSet expand (default 500)

8. Multi-Region Notes

Terminology data (SNOMED, LOINC, etc.) is non-PHI and may be deployed from a shared global read replica if latency allows. For edge/offline deployments (e.g., rural Afghan health posts), a snapshot bundle is packaged and deployed alongside the service — see SYNC_CONTRACT.md for offline snapshot strategy.