Skip to content

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;
  • pg as 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:

  1. trusted application-level tenant scoping; and
  2. 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.