2026-06-107 min

Cómo la Seguridad a Nivel de Fila de Postgres Hace a Ops Blindado para Operaciones Multi-Tenant

Cómo la Seguridad a Nivel de Fila de Postgres Hace a Ops Blindado para Operaciones Multi-Tenant

El Problema de Seguridad Multi-Tenant

Ejecutar una plataforma SaaS multi-tenant significa una cosa por encima de todo: los datos del tenant nunca deben filtrarse entre cuentas. Esto parece obvio, pero los detalles de implementación son donde la mayoría de las plataformas fallan.

El enfoque ingenuo — agregar una cláusula `WHERE tenant_id = ?` a cada consulta — es frágil por diseño. Requiere que cada desarrollador, cada consulta ORM y cada ruta de código futura recuerde ese filtro. Un solo `WHERE` olvidado, un ORM mal configurado o un JOIN complejo que elimine el filtro — y los datos de tu tenant quedan expuestos.

Ops resuelve este problema a nivel de base de datos, no a nivel de aplicación.

Row-Level Security: Seguridad Que No Puede Ser Evitada

La Seguridad a Nivel de Fila (RLS) de PostgreSQL es un mecanismo de imposición del lado del servidor. Cuando se aplica una política a una tabla, la propia base de datos filtra las filas según el contexto de la sesión actual — antes de devolver datos a la aplicación.

Así se ve una política RLS simplificada en Ops:

```sql

-- Habilitar RLS en la tabla de productos

ALTER TABLE products ENABLE ROW LEVEL SECURITY;

-- Forzar RLS incluso para el propietario de la tabla (¡crítico!)

ALTER TABLE products FORCE ROW LEVEL SECURITY;

-- Crear la política de aislamiento

CREATE POLICY tenant_isolation ON products

USING (tenant_id = current_setting('app.current_tenant')::uuid);

```

Con esta política en vigor, incluso si un error de aplicación ejecuta `SELECT * FROM products` sin ninguna cláusula WHERE, PostgreSQL restringirá automáticamente los resultados a solo las filas que pertenecen al tenant actual. La base de datos impone el límite — no el código de la aplicación.

El Patrón de Contexto de Sesión

La clave para hacer funcionar RLS en un entorno de pool de conexiones es el contexto de sesión. Cuando un usuario se autentica, Ops establece una variable local de sesión:

```sql

SET LOCAL app.current_tenant = '550e8400-e29b-41d4-a716-446655440000';

```

Esta variable vive solo durante la transacción. No puede filtrarse entre conexiones. No puede ser sobrescrita accidentalmente por una solicitud concurrente. Cuando la transacción se confirma o revierte, el contexto desaparece.

Más Allá del Aislamiento Simple: Visibilidad de Filas Basada en Roles

RLS en Ops va más allá del simple aislamiento de tenant. También impulsa el acceso basado en roles de grano fino:

  • Los vendedores solo pueden ver los pedidos que crearon.
  • Los gerentes de sucursal pueden ver todos los pedidos de su sucursal, pero no de otras sucursales.
  • Los gerentes regionales pueden ver todos los pedidos en su región asignada.
  • Los propietarios tienen visibilidad total.

Todo esto se expresa como políticas RLS componibles — sin sentencias switch en la capa de aplicación, sin middleware, sin verificaciones de permisos dispersas en todo el código.

Rendimiento: La Preocupación Común

Una objeción frecuente a RLS es el rendimiento. ¿Será la base de datos más lenta si está filtrando filas en cada consulta?

En la práctica, para la carga de trabajo de Ops, el impacto es insignificante porque:

  • `tenant_id` siempre está indexado. El filtro RLS se aplica temprano en el plan de consulta, antes de cualquier join o agregación costosa.
  • Índices parciales. Ops usa índices parciales por tenant para las tablas más frecuentemente accedidas, lo que significa que el índice en sí está pre-filtrado.
  • La alternativa es peor. El filtrado en la capa de aplicación requiere leer todas las filas y filtrar en memoria (catastrófico a escala) o agregar cláusulas WHERE complejas que el planificador de consultas puede no optimizar tan eficientemente como una política integrada.

Rastros de Auditoría como Característica de Primera Clase

Debido a que cada escritura de fila pasa por la base de datos, Ops puede adjuntar disparadores de auditoría conscientes de RLS a cualquier tabla, registrando cada INSERT, UPDATE y DELETE con contexto de tenant, contexto de usuario y marca de tiempo — automáticamente, sin que la aplicación necesite recordar llamar a una función de registro.

La seguridad que vive en la base de datos es seguridad que puede probarse.

¿Listo para probar Ops?

Crea tu cuenta, instala lo que usas y empieza a vender el mismo día.

Empieza gratis en 5 minutos
Volver al blog