Skip to main content

Multi-Tenancy

Ignixa supports multi-tenant deployments with physical data isolation between tenants.

Overview

Multi-tenancy enables a single Ignixa deployment to serve multiple isolated healthcare organizations, each with their own:

  • Data partition
  • Configuration
  • Access controls

Tenant Routing

In multi-tenant mode, resources are accessed via tenant-prefixed URLs:

/tenant/{tenantId}/{resourceType}/{id}

Single Tenant Mode

# Both work
GET /Patient/123
GET /tenant/1/Patient/123

Multi-Tenant Mode

# Only tenant-prefixed routes work
GET /tenant/1/Patient/123 ✅
GET /tenant/2/Patient/456 ✅
GET /Patient/123 ❌ 400 Bad Request

Configuration

Enable multi-tenancy in appsettings.json:

{
"Tenancy": {
"Mode": "MultiTenant",
"DefaultTenantId": 1
}
}
SettingDescription
ModeSingleTenant or MultiTenant
DefaultTenantIdFallback tenant for ambiguous requests

Reserved Tenant

Tenant 0 is Reserved

Tenant ID 0 is reserved for system operations and cannot be accessed via the API.

GET /tenant/0/Patient/123    ❌ 400 Bad Request

The system tenant stores:

  • Transaction ID sequences
  • System-level metadata
  • Internal state

Data Isolation

Each tenant has physically separate data:

┌─────────────────────────────────────────┐
│ SQL Server │
├─────────────┬─────────────┬─────────────┤
│ Tenant 1 │ Tenant 2 │ Tenant 3 │
│ │ │ │
│ ┌─────────┐ │ ┌─────────┐ │ ┌─────────┐ │
│ │ Patient │ │ │ Patient │ │ │ Patient │ │
│ │ Observ. │ │ │ Observ. │ │ │ Observ. │ │
│ │ ... │ │ │ ... │ │ │ ... │ │
│ └─────────┘ │ └─────────┘ │ └─────────┘ │
└─────────────┴─────────────┴─────────────┘

Isolation Guarantees

  • ✅ Queries cannot cross tenant boundaries
  • ✅ References are validated within tenant
  • ✅ Search results are tenant-scoped
  • ✅ Bundles process within single tenant

Middleware Flow

// Request: GET /tenant/2/Patient/123

1. TenantResolutionMiddleware
- Extract tenantId = 2 from route
- Validate: tenantId != 0
- Set HttpContext.Items["TenantId"] = 2

2. Handler Execution
- Repository uses scoped tenant context
- All operations filtered by tenantId

3. Response
- Links include tenant prefix
- CapabilityStatement reflects tenant config

Azure Deployment

For Azure deployments, each tenant can have dedicated resources:

{
"Tenancy": {
"Mode": "MultiTenant",
"TenantConfiguration": {
"1": {
"ConnectionString": "Server=tenant1-sql.database.windows.net;..."
},
"2": {
"ConnectionString": "Server=tenant2-sql.database.windows.net;..."
}
}
}
}

Provisioning Tenants

Tenants are provisioned via configuration in appsettings.json:

{
"Tenants": {
"Mode": "Isolated",
"Configurations": [
{
"Id": 1,
"DisplayName": "Hospital A",
"FhirVersion": "R4B",
"Storage": {
"Type": "SqlServer",
"ConnectionString": "Server=localhost;Database=fhir_tenant1;..."
}
},
{
"Id": 2,
"DisplayName": "Clinic B",
"FhirVersion": "R4",
"Storage": {
"Type": "SqlServer",
"ConnectionString": "Server=localhost;Database=fhir_tenant2;..."
}
}
]
}
}

Each tenant can have:

  • Different FHIR versions (R4, R4B, R5)
  • Different storage backends (SQL Server, FileSystem, Blob Storage)
  • Different search configurations
  • Isolated access controls