Cell directory — How it works
Overview
The cell directory is the cloud tier's answer to one question: which cell holds this tenant's
data? It is a small Maven module, cloud/directory, deployed with the cloud tier rather than with a
facility instance. It is the only component that knows the mapping; a cell itself decides residency
locally (see Cell residency).
⚠⚠ The directory holds no patient data, and that is enforced by a test.
DirectorySchemaHoldsNoPatientDataTest fails the build if the schema grows a column that could carry
one. A routing table that accumulated demographics would become a national patient index by accident —
exactly the thing the cell model is designed to make impossible.
Data model & ownership
| Table | Purpose |
|---|---|
cell | One row per cell: code (unique, e.g. NG-1), country_code, api_base_url, health_url, active. |
tenant_cell_assignment | tenant_id → cell_id, with assigned_at. One assignment per tenant. |
Migrations live under cloud/directory/src/main/resources/db/changelog/directory/, with the module's
own master at directory.db.changelog-master.yaml. The module ships its defaults in
uhp-module-defaults.yml per CONF-002.
The registry
CellRegistry exposes two operations:
resolveCell(tenantId)→Optional<Cell>evict(tenantId)— forget any cached assignment
CellRegistryImpl caches resolutions with a short TTL, because a routing lookup sits in front of
cloud request handling and must not become a per-request database round trip.
Key rules & invariants
- An unknown tenant resolves to nothing, never to a default. A "sensible fallback" would route a
tenant nobody has assigned into some other country's cell — the exact failure the cell model exists
to prevent — and it would look like a working request while doing it.
Optional.empty()is the correct answer and callers must handle it. - The cache must be invalidable.
evictexists because a cell migration has to take effect. A cache that could not be invalidated would keep routing a migrated tenant to the cell that no longer holds its data, and the symptom would be missing records rather than an error. - The directory is not on the cell's critical path. A cell answers residency from its own database, so the directory being unreachable degrades routing, not care delivery.
country_codeis on the cell, not derived. Which country a cell serves is a deployment fact and a residency commitment, not something to infer from a tenant's address.
Related
- Cell residency — how an individual cell refuses a request it should not answer.