Dentolize · Regional DB Split Walkthrough
On this pageTermsGlobal-schema data model (selected)Regional-schema data model

Glossary & Data Model

Terms

TermMeaning
RegionAn independent deployment unit with its own database, Redis, and (usually) storage bucket — e.g. EU-1, ME-1. Identified everywhere by a REGION_CODE like EU-1 or ME-1.
Global databaseThe one shared PostgreSQL database (schema.global.prisma) holding admins, referrals, the region directory, routing/mapping tables, and shared catalogs. Read-only from regional servers; writable only via the Auth Server.
Regional databaseA per-region PostgreSQL database (schema.regional.prisma, auto-generated) holding all tenant data: companies, patients, appointments, invoices, etc.
Auth ServerNew standalone service (packages/auth-server) that resolves "which region is this account in" and hosts admin login, cross-region registration, and the admin dashboard's cross-region GraphQL API.
Regional serverThe existing packages/server API/cron/queue processes, one deployment per region, each backed by that region's own database.
Region lookupThe REST call (/api/lookup, /api/lookup-company, etc.) a client makes before login/registration/public-link access to find which region's API to talk to.
Fake regionA deterministic-but-meaningless region returned by a lookup for an email/company that doesn't exist, so failed lookups can't be used to enumerate real accounts.
Company routing hintA short encoded string (?c=...) appended to public/QR links so the recipient's browser can resolve the right region without a slow all-region scan.
Internal GraphQLA second, separately-authenticated GraphQL endpoint (/internal/graphql) on each regional server, used only for server-to-server admin/cron/redis calls from the Auth Server — not reachable via normal user login.
INTERNAL_API_KEYShared static bearer token that authenticates internal-GraphQL and user/company-mapping-sync calls between the Auth Server and regional servers.
Migration ledgerThe CompanyRegionMigration record (plus its progress/lock tables) in the global database that tracks the state of one company's region-to-region move — status, row counts, timestamps, last error.
Fence (Redis)A temporary marker set during a real company migration that write paths are expected to check and reject/skip writes for a fenced company, so no new writes land mid-copy.
BlockerIn-flight company work (pending upload, unpaid online payment, in-progress e-invoice submission) that prevents a migration from freezing and copying the company's data.
CutoverThe point in a company migration where global routing tables are updated to point at the target region — before cutover, undoing the migration just means discarding target data; after cutover, the source is the one considered stale.
Soft referenceA foreign-key column kept on a regional model that used to @relation to a now-global model (e.g. Company.referralId); the column stays, but Prisma can no longer traverse the relation across the two separate databases.

Global-schema data model (selected)

  • Region — one row per deployment region (code, name, status).
  • CompanyRegion — which region currently owns a given company; the record cutover updates.
  • CompanyRegionMigration (+ CompanyRegionMigrationTableProgress, CompanyRegionMigrationStorageProgress, CompanyRegionMigrationCompanyLock) — the migration ledger described above.
  • UserRegionMapping — email → region, kept in sync by regional servers via the /internal/user-mapping webhook.
  • CompanyLoginNameMapping — clinic login name → region, kept in sync via /internal/company-mapping.
  • RegistrationWorkflow — idempotency/state tracking for cross-region signups in progress.
  • Admin, Referral — Dentolize staff and referral-partner accounts; these stay global since they're not scoped to a single clinic/region.
  • CompanyPayment — kept global specifically because it references Admin.
  • GlobalInventoryItem, GlobalMedication, GlobalCondition — shared catalogs every region reads but doesn't own.
  • FeatureFlag — global feature-flag definitions.

Regional-schema data model

Everything else — Company, User, Patient, Appointment, Invoice, and the other ~130 models that make up the existing clinic product — lives unchanged (same fields, same relationships to each other) in the regional schema. The regional schema is generated automatically from the pre-existing monolith schema.prisma, so there is no new data modeling here — only a new boundary around where that data is hosted.