ADR-011 — Persistence, Tenant Isolation and Geospatial Baseline¶
Status: ACCEPTED — I1-B3 Technology Decision Gate
Accepted: 2026-09-21
Context¶
Touriffique needs strong transactional integrity, schema-controlled vertical extensibility, tenant isolation and first-class geospatial operations across properties, marinas, vehicles, excursions and service areas.
The modular-monolith architecture also benefits from physical persistence ownership boundaries without prematurely creating a database per engine.
Decision¶
Database and ORM¶
Use:
- PostgreSQL 18;
- PostGIS 3.6.x;
- TypeORM 1.x with
@nestjs/typeorm; pgas the PostgreSQL driver;- Data Mapper/repository style rather than Active Record/
BaseEntity.
Schema ownership¶
Use one physical PostgreSQL database initially, with engine-owned schemas:
platform
capability
commerce
site
crm
marketing
channel
finance
integration
operations
i18n
Migrations¶
Production schema evolution is controlled exclusively by explicit versioned migrations.
synchronize: true is forbidden in persistent production/staging environments.
Raw PostgreSQL SQL inside migrations is acceptable for PostgreSQL-specific features such as RLS, PostGIS, indexes, constraints and database functions.
Tenant isolation¶
Tenant-owned rows carry tenant_id.
Isolation is enforced by:
- trusted application-level tenant scoping; and
- PostgreSQL RLS as defense in depth.
Tenant DB context is transaction-local so pooled connections cannot retain another tenant's context.
Normal tenant runtime access is separated from privileged platform/migration access.
IDs¶
UUIDv7 is the default identifier format for major platform/domain aggregates.
Extensible data¶
Use JSONB only for schema-controlled/versioned extensible data and suitable structured provider/document data.
Strong transaction state remains explicitly modeled.
Geospatial¶
PostGIS is authoritative for spatial persistence/querying.
- ordinary earth-location points default to
geography(Point,4326); - boundaries/service areas use an appropriate PostGIS geometry/geography type, with
geometry(...,4326)the default topology baseline; - WGS84/SRID 4326 is the default interchange CRS;
- GiST indexes are used where query patterns require them;
- spatial predicates/distances are executed by PostGIS rather than application-side Haversine implementations.
Optional PostGIS modules are not enabled without a concrete requirement.
Consequences¶
- tenant isolation does not depend on developers remembering a single ORM filter;
- persistent engine ownership is visible without requiring separate databases;
- TypeORM abstractions can be bypassed deliberately in migrations/queries where PostgreSQL capabilities matter;
- PostGIS supports native radius, containment and spatial-index behavior;
- the stack accepts PostgreSQL-specific capabilities instead of pretending persistence is database-agnostic;
- production migrations and RLS require PostgreSQL/PostGIS integration testing;
- later database/service extraction remains possible because engine ownership is explicit.