PostgreSQL multiempresa: tres estrategias para aislar datos de clientes en un SaaS
Publicado el 2026-11-14 por frfrand
Compara bases por cliente, esquemas independientes y tablas compartidas con tenant_id y RLS, con criterios de seguridad, coste y operación.

Si tu SaaS atiende a varias empresas, el problema no es solo guardar una columna empresa_id: es asegurar que ningún error permita ver o modificar información de otra empresa. PostgreSQL ofrece tres arquitecturas habituales, con diferentes costes de desarrollo, despliegue y operación.
1. Una base de datos por empresa
Cada cliente obtiene una base distinta. Esto facilita establecer políticas de acceso separadas, migraciones graduadas y ciertas estrategias de backup o restauración por cliente. A cambio, crece el número de conexiones, recursos y operaciones que debes administrar.
Es apropiado cuando hay exigencias fuertes de aislamiento, necesidades específicas por cliente o tamaños de datos muy diferentes. No elimina automáticamente los fallos de autorización de la aplicación.
2. Un esquema por empresa
Las tablas viven dentro de distintos esquemas de una misma instancia de PostgreSQL. Aíslas nombres y estructuras, pero compartes CPU, RAM, almacenamiento y administración del servidor. Debes revisar cuidadosamente search_path, roles, permisos y migraciones: elegir el esquema equivocado puede producir una filtración.
Este modelo puede equilibrar separación lógica y coste, aunque una gran cantidad de tenants multiplica las operaciones de mantenimiento y los cambios de esquema.
3. Tablas compartidas con tenant_id
Clientes distintos comparten tablas como orders y users, con una columna tenant_id por fila. Simplifica migraciones y análisis conjunto, pero exige disciplina extrema de consultas y autorización.
Ejemplo de diseño conceptual:
CREATE TABLE orders (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
tenant_id uuid NOT NULL,
external_ref text NOT NULL,
UNIQUE (tenant_id, external_ref)
);
CREATE INDEX orders_tenant_id_idx ON orders (tenant_id);
La unicidad compuesta evita choques entre referencias de empresas. Añade restricciones entre tablas que incluyan tenant_id para impedir relaciones cruzadas accidentalmente.
4. Aislamiento con Row Level Security
RLS permite aplicar políticas por fila dentro de PostgreSQL. Por ejemplo, puedes asociar la empresa actual a la conexión o transacción y exigir que tenant_id coincida con ese contexto. Implementarlo requiere roles sin privilegios de bypass, políticas correctas de lectura y escritura y mucho cuidado con connection pooling para que el contexto de un cliente no se herede por otro.
No basta con activar RLS: las políticas pueden faltar y usuarios privilegiados o propietarios pueden comportarse de forma distinta. Prueba ataques de acceso cruzado mediante un usuario de aplicación real.
5. Comparación para tomar la decisión
| Estrategia | Ventaja | Coste técnico | |---|---|---| | Base por cliente | Separación operativa más fuerte | Multiplicar backups, conexiones y migraciones | | Esquema por cliente | Estructura separada | Gestionar schemas, roles y search_path | | Tabla compartida | Simplicidad de esquema y eficiencia | Máxima atención a políticas y filtros |
Para un producto nuevo con muchos clientes pequeños, tablas compartidas con RLS y pruebas rigurosas pueden ser suficientes. Para clientes regulados o muy grandes, conviene estudiar mayor separación.
6. Pruebas obligatorias antes de lanzar
Crea dos tenants con datos deliberadamente parecidos. Intenta listar, leer, actualizar y borrar objetos de la otra empresa, también usando referencias directas. Verifica permisos en exports, procesos batch, colas y tareas administrativas. Asegura que backups y restauraciones respeten la separación requerida.
Profundiza en Supabase RLS con ejemplos, qué es RLS en PostgreSQL y PostgreSQL en ArduMaker.
Preguntas frecuentes
### ¿Una base independiente es completamente segura? Aumenta el aislamiento, pero no sustituye controles de aplicación y credenciales.
¿RLS reemplaza la autorización del backend?
No. Complementa los controles de acceso, no los elimina.
¿Puedo cambiar de modelo después?
Sí, pero requiere migración planificada de datos, permisos y lógica de aplicación.
Referencia: PostgreSQL Row Security Policies.