Skip to main content

Aislamiento multi-tenant impuesto por la base de datos, no por el código

SaaSNext.jsPostgreSQL RLSDrizzleEn desarrollo
El aislamiento entre municipios lo impone Postgres con RLS, no el código de aplicación

El Desafío

  • Un municipio nunca ve al otro: cada tabla operativa lleva su ayuntamiento y FORCE ROW LEVEL SECURITY; pedir un recurso ajeno por ID responde 404, nunca 403
  • Tenant dentro de la transacción: se fija con SET LOCAL, nunca con un SET suelto — el pooler recicla conexiones y el siguiente request podría ser de otro municipio
  • Rejas automáticas, no disciplina: una tabla nueva sin prueba de aislamiento no entra, y un test de esquema recorre Postgres y tumba el build si encuentra una tabla de municipio sin RLS activo
  • Límites de capa verificados: ui → application → domain ← infrastructure, con el dominio sin importar nada; dependency-cruiser lo revisa en pre-push y en CI

Arquitectura de la Solución

HostTenantLayersSessionSET LOCALayuntamiento.xulasigma.mxproxy.tsApp RouterBetter Authui → application → domainwithTenantDrizzle ORMPostgreSQL + RLS
System architecture diagram showing nodes and connections

Resolución por subdominio

El municipio se resuelve desde el Host en el proxy de Next.js, antes que la sesión. El login corre dentro de la misma capa de tenancy que cualquier otra tabla.

Capa de tenancy

Todo acceso a datos pasa por withTenant: abre transacción, fija el tenant con SET LOCAL y deja que la política RLS haga el filtrado. No hay conexión directa a la base.

Base de datos

PostgreSQL con Drizzle ORM, elegido por RLS y por el control explícito de la transacción. Roles separados para migración y aplicación: ninguno es superusuario ni puede saltarse RLS.

Calidad

Especificación primero (SDD) y TDD estricto: pruebas unitarias y de aislamiento en Vitest, E2E en Playwright, Biome para lint y formato, dependency-cruiser para los límites de capa.

Resultados

RLS

Aislamiento en la base, no en el código

SDD + TDD

Especificación escrita antes del código, prueba antes de la implementación

0 BYPASSRLS

Ningún rol de la aplicación puede saltarse la política

XULA SIGMA - SaaS Multi-Tenant Municipal | Joel May