Clinora Architecture
Clinora uses a database-per-tenant architecture to provide strong data isolation between clinics.
Topology
┌─────────────────────┐
│ Application │
│ (Next.js API) │
└──────────┬──────────┘
│
├──────────────────────┐
│ │
┌──────────▼──────────┐ ┌────────▼──────────┐
│ Manager Database │ │ Tenant Databases │
│ │ │ │
│ - Tenants │ │ tenant_acme │
│ - Users (global) │ │ tenant_hospital │
│ - Licenses │ │ tenant_clinic │
│ - Billing │ │ ... │
└─────────────────────┘ └───────────────────┘
Manager Database
The manager database holds the control plane:
- Tenant registry — List of all provisioned tenants, their DB connection strings, and status
- Global users — Platform-wide identity for administrators and cross-tenant roles
- Licensing — License entitlements and feature flags per tenant
- Billing — Platform-level billing data
Tenant Databases
Each tenant receives a dedicated database (tenant_<slug>) containing:
- Patients and medical records
- Providers and staff
- Appointments and schedules
- Clinical documentation
- Billing and insurance claims
- Inventory and procurement
Local Development
When developing locally, you must provision both the manager database AND at least one tenant database. The app won't function without both.
Request Flow
- Client authenticates — JWT includes tenant identifier
- Middleware resolves tenant DB connection from manager DB
- Request handlers operate against the tenant-specific DB
- Response returned to client
Why Database-per-Tenant?
- Strong isolation — Physical separation of data between clinics
- Backup/restore — Per-tenant backups, point-in-time recovery
- Compliance — Simpler data residency and right-to-erasure workflows
- Scaling — Noisy neighbors don't affect other tenants