Database Isolation
The MATIH Platform uses Hibernate's schema-based multi-tenancy to isolate tenant data at the database level. Each tenant's data resides in a separate PostgreSQL schema within a shared database, providing strong data isolation without the operational overhead of separate database instances.
Schema-Per-Tenant Model
PostgreSQL Database: matih_ai
+-- Schema: system (platform metadata)
+-- Schema: acme_corp (Tenant: ACME Corporation)
+-- Schema: globex (Tenant: Globex Inc.)
+-- Schema: initech (Tenant: Initech LLC)Each schema contains identical table structures. Hibernate routes queries to the correct schema based on the current tenant context.
TenantIdentifierResolver
The TenantIdentifierResolver integrates with Hibernate to resolve the current tenant:
@Component
public class TenantIdentifierResolver
implements CurrentTenantIdentifierResolver<String> {
@Override
public String resolveCurrentTenantIdentifier() {
return TenantContext.getCurrentTenantIdOrDefault("system");
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}Before each query, Hibernate sets the PostgreSQL search path:
SET search_path TO 'acme_corp';
SELECT * FROM dashboards WHERE created_by = 'user-123';Hibernate Configuration
spring:
jpa:
properties:
hibernate:
multiTenancy: SCHEMA
tenant_identifier_resolver:
com.matih.commons.persistence.multitenancy.TenantIdentifierResolverConnection Pool Management
Each service maintains a single HikariCP connection pool shared across all tenants:
| Parameter | Development | Production |
|---|---|---|
| Pool size | 10 | 30 |
| Min idle | 2 | 5 |
| Connection timeout | 30s | 10s |
The TenantIdentifierResolver sets the schema on each connection before use, ensuring correct routing without per-tenant pools.
Schema Provisioning
When a new tenant is provisioned, the Tenant Service creates schemas:
| Step | Action |
|---|---|
| 1 | Create schema: CREATE SCHEMA IF NOT EXISTS {tenant_slug} |
| 2 | Run Flyway/Alembic migrations against the new schema |
| 3 | Seed initial data (default dashboards, configurations) |
| 4 | Verify schema structure matches system schema |
Backup and Migration
| Operation | Method |
|---|---|
| Per-tenant backup | pg_dump --schema={tenant_slug} |
| Tenant migration | Export schema from source, import to target database |
| Schema comparison | Compare tenant schema against system schema |
| Data purge | Drop tenant schema on decommission |
Isolation Guarantees
| Guarantee | Mechanism |
|---|---|
| No cross-tenant queries | Hibernate sets search_path per request |
| No missing tenant filter | requireTenantId() throws if context is absent |
| Schema independence | Each schema is a complete, isolated namespace |
| Connection isolation | Schema set on connection checkout, cleared on return |
Related Pages
- Tenant Context -- How context drives schema selection
- Namespace Isolation -- Kubernetes-level isolation
- Data Stores: PostgreSQL -- PostgreSQL architecture