Skip to main content

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

TablePurpose
cellOne row per cell: code (unique, e.g. NG-1), country_code, api_base_url, health_url, active.
tenant_cell_assignmenttenant_idcell_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. evict exists 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_code is 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.
  • Cell residency — how an individual cell refuses a request it should not answer.