Módulo 15 · Arquitectura y migración/Lección 95
SaaS multiinquilino en AWS
Muchos clientes en una misma plataforma: modelos de aislamiento, datos por cliente, límites por inquilino y costos por cliente.
⏱ 12 min
Al terminar podrás
- →Diferenciar los modelos silo, pool y puente
- →Aislar los datos de cada cliente
- →Evitar que un cliente afecte a los demás
Un SaaS atiende a muchos clientes desde una misma plataforma. Cada cliente es un inquilino (tenant): una empresa con sus usuarios, sus datos y su plan. Tres preguntas guían el diseño: cómo evitas que un inquilino vea los datos de otro, cómo evitas que uno afecte a los demás y cómo sabes cuánto cuesta cada uno.
Silo, pool y puente
| Criterio | Silo | Pool | Puente (bridge) |
|---|---|---|---|
| Qué se comparte | Identidad, alta y operación. Los recursos son dedicados por inquilino | Todo: cómputo, base de datos, colas | Unas partes dedicadas y otras compartidas |
| Aislamiento | El más fuerte: por cuenta, VPC o base de datos | Lógico: depende de políticas y del código | Fuerte donde los datos lo exigen, lógico en el resto |
| Costo por inquilino | Alto: pagas recursos aunque estén ociosos | Bajo: economía de escala | Intermedio |
| Vecino ruidoso | Casi no existe | Riesgo real; necesitas límites | Controlado en los componentes dedicados |
| Operación | Muchas copias que desplegar y vigilar | Una sola plataforma | Dos modelos que mantener |
| Cuándo | Clientes regulados o que pagan por aislamiento | Muchos clientes pequeños | Lo más común en la práctica |
Un silo fuerte puede ser una cuenta de AWS por inquilino dentro de tu organización. Lo habitual es combinar: un nivel premium en silo y los planes básicos en pool.
Datos por cliente
Con tablas compartidas, no confíes solo en que cada consulta recuerde el WHERE tenant_id = .... En PostgreSQL (RDS o Aurora), la seguridad a nivel de fila (row-level security) hace que la base aplique el filtro por ti:
-- Cada fila lleva el inquilino dueño
ALTER TABLE facturas ENABLE ROW LEVEL SECURITY;
ALTER TABLE facturas FORCE ROW LEVEL SECURITY; -- aplica también al dueño de la tabla
CREATE POLICY aislamiento_inquilino ON facturas
USING (tenant_id = current_setting('app.tenant_id')::uuid);
-- En cada transacción, la aplicación fija el inquilino que viene en el token
BEGIN;
SET LOCAL app.tenant_id = '6f1c2a9e-0000-4000-8000-000000000001';
SELECT * FROM facturas; -- solo ve las facturas de ese inquilino
COMMIT;SET LOCAL dura solo la transacción, así que una conexión reutilizada del pool no arrastra el inquilino anterior. Ojo: los superusuarios y los roles con BYPASSRLS se saltan las políticas; la aplicación debe conectarse con un rol sin esos privilegios.
El contexto del inquilino viaja en el token
- 1
El usuario inicia sesión
Amazon Cognito emite un token con el inquilino: un atributo personalizado comocustom:tenant_iden el token de identidad, o un claim agregado con el disparador pre token generation. - 2
La API valida el token
El autorizador de API Gateway verifica la firma. El servicio toma el inquilino del token, nunca de un parámetro que manda el cliente. - 3
Credenciales con la etiqueta del inquilino
El servicio asume un rol con una session tagtenant_id. La política usa esa etiqueta para limitar el acceso: es control de acceso basado en atributos (ABAC). - 4
La base aplica el filtro
DynamoDB revisa la clave de partición contra la etiqueta; PostgreSQL aplica la política de fila con el valor fijado en la transacción.
{
"Effect": "Allow",
"Action": ["dynamodb:GetItem", "dynamodb:Query", "dynamodb:PutItem"],
"Resource": "arn:aws:dynamodb:*:*:table/Pedidos",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${aws:PrincipalTag/tenant_id}"]
},
"Null": { "dynamodb:LeadingKeys": "false" }
}
}Con la clave de partición empezando por el inquilino, esta política solo deja leer y escribir ítems de ese inquilino. Un solo rol sirve para todos: el valor llega en la sesión. Más sobre roles y políticas en IAM.
El vecino ruidoso: límites por inquilino
En pool, un cliente que lanza una importación masiva puede volver lenta la plataforma para todos. Es el vecino ruidoso. Las defensas van por capas:
- Planes de uso de API Gateway (usage plans, en APIs REST): una API key por inquilino o por nivel, con límite de peticiones por segundo y cuota por periodo.
- Colas por inquilino o por nivel, para que un lote enorme no bloquee a los demás.
- Concurrencia reservada de Lambda para separar las funciones de los clientes premium.
- Reglas basadas en tasa de AWS WAF como protección adicional frente a abusos.
Medir y cobrar por inquilino
Sin medidor no sabes si un cliente te da ganancia o pérdida. Emite métricas y logs con el tenant_id: peticiones, latencia, errores, almacenamiento. Cuidado con usar el inquilino como dimensión de métricas cuando tienes miles: cada combinación es una métrica que se cobra. Para muchos inquilinos, usa logs estructurados y consultas.
El costo depende del modelo. En silo, etiqueta cada recurso con tenant y activa la etiqueta como etiqueta de asignación de costos en la consola de facturación: sin activarla no aparece en Cost Explorer. En pool no hay recurso que etiquetar; repartes el costo compartido según el consumo que mides. Más en controlar costos.
Alta automática y datos sensibles
El alta de un inquilino nuevo (onboarding) debe ser un proceso automático, no un ticket: registrar el inquilino, crear su administrador en Cognito, aprovisionar sus recursos (una pila de infraestructura como código en silo, unas filas de configuración en pool), asignarle su plan de uso y su llave de cifrado. Si toma un día y depende de una persona, no escala.
Con datos personales o financieros, suma dos controles:
- Cifrado por inquilino: una llave de AWS KMS por inquilino o por nivel, con el
tenant_idcomo contexto de cifrado. Así cada acceso a la llave queda auditado por cliente. Ve cifrado y secretos. - Residencia de datos: los inquilinos de un país viven en una región de ese país, con su propia copia de la plataforma. Ve cumplimiento.
Quiz
Pon a prueba lo que aprendiste
0 de 5 correctas · 5 sin responder
1.Un SaaS da a cada cliente premium su propia base de datos, pero todos comparten el cómputo, el inicio de sesión y el proceso de alta. ¿Qué modelo es?
2.Todos los inquilinos comparten tablas en Aurora PostgreSQL. ¿Qué agrega una segunda barrera si un desarrollador olvida el filtro por inquilino?
3.Un cliente hace una importación masiva y la API se vuelve lenta para todos. ¿Qué medida apunta directo al problema?
4.¿De dónde debe salir el identificador del inquilino en cada petición?
5.Los recursos de cada inquilino en silo tienen la etiqueta tenant, pero no aparecen agrupados en Cost Explorer. ¿Qué falta?