Creación de un SaaS multicliente: base de datos por cliente frente a esquema compartido
La decisión arquitectónica más importante en el desarrollo de SaaS: cómo aislar los datos de los clientes. Comparamos tres enfoques con análisis de costes reales, estrategias de migración y ejemplos de código.
La decisión que lo determina todo
A la hora de desarrollar un producto SaaS, la decisión arquitectónica más importante es el aislamiento de los clientes. Si te equivocas, acabarás dedicando meses a la migración más adelante. Existen tres enfoques, cada uno con sus claras ventajas e inconvenientes:
Enfoque 1: Base de datos compartida, esquema compartido (aislamiento a nivel de fila)
Los datos de todos los clientes se almacenan en las mismas tablas, diferenciados por una columna «tenant_id». Este es el método más sencillo y económico.
# Django: automatic tenant filtering with middleware
class TenantMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Set tenant from JWT or subdomain
request.tenant = get_tenant_from_request(request)
return self.get_response(request)
class TenantManager(models.Manager):
def get_queryset(self):
from threading import local
_thread_locals = local()
tenant = getattr(_thread_locals, 'tenant', None)
qs = super().get_queryset()
if tenant:
qs = qs.filter(tenant_id=tenant.id)
return qs
class Order(models.Model):
tenant = models.ForeignKey('Tenant', on_delete=models.CASCADE)
# ... other fields
objects = TenantManager() # All queries auto-filteredVentajas: Sencillo, económico (entre 50 y 200 dólares al mes por una base de datos), fácil de implementar, grupo de conexiones compartido. Desventajas: Riesgo de fugas de datos si se olvida aplicar un filtro, problema de «vecinos ruidosos» (las consultas pesadas de un usuario afectan a los demás), mayor dificultad para cumplir con la normativa (eliminación de datos según el RGPD).
Enfoque 2: Base de datos compartida, esquemas independientes (esquemas de PostgreSQL)
Cada usuario dispone de su propio esquema de PostgreSQL dentro de una misma base de datos. Las tablas son idénticas, pero están aisladas por espacio de nombres.
# Using django-tenants library
# Each request sets the schema based on subdomain
# settings.py
DATABASE_ROUTERS = ['django_tenants.routers.TenantSyncRouter']
# Middleware sets schema per request
# acme.yourapp.com -> schema 'acme'
# globex.yourapp.com -> schema 'globex'
# SQL equivalent:
# SET search_path TO 'acme'; -- all queries now hit acme's tables
# SELECT * FROM orders; -- returns only acme's ordersVentajas: Aislamiento sólido sin bases de datos adicionales, fácil eliminación de datos (DROP SCHEMA CASCADE), índices independientes por cliente. Desventajas: Complejidad de la migración (hay que migrar todos los esquemas), la gestión de la piscina de conexiones es más complicada, máximo de unos 500 clientes antes de que el rendimiento se vea afectado.
Enfoque 3: Una base de datos por cliente
Cada cliente dispone de su propia base de datos. Máximo aislamiento, máxima complejidad operativa.
Ventajas: Aislamiento total, escalabilidad independiente, fácil cumplimiento normativo, posibilidad de ofrecer infraestructura dedicada a clientes empresariales. Desventajas: Caro (entre 50 y 200 dólares al mes por inquilino), la gestión de grupos de conexiones es una pesadilla, las migraciones abarcan cientos de bases de datos y el análisis entre inquilinos requiere un almacén de datos.
Matriz de decisión: ¿qué enfoque elegir?
| Factor | Esquema compartido | Esquemas independientes | Bases de datos independientes |
|---|---|---|---|
| Coste mensual (100 inquilinos) | entre 100 y 200 dólares | entre 200 y 500 dólares | entre 5.000 y 20.000 dólares |
| Límite del número de inquilinos | Ilimitado | ~500 | ~100 (dominable) |
| Aislamiento de datos | Débil (a nivel de fila) | Fuerte (a nivel de esquema) | Completo |
| Cumplimiento normativo (RGPD/SOC 2) | Difícil | Moderado | Fácil |
| Riesgo de tener vecinos ruidosos | Alto | Medio | Ninguno |
| Ideal para | B2C, SaaS para pymes | SaaS para el mercado medio | SaaS para empresas |
Nuestra recomendación: Empieza con Shared y luego pasa a un plan superior
Empieza con un esquema compartido y aislamiento a nivel de fila. Así podrás lanzar el producto al mercado rápidamente y cubrirás el 90 % de los casos de uso. Cuando consigas clientes empresariales que necesiten garantías de aislamiento, ofréceles esquemas o bases de datos independientes como nivel premium.
La clave está en diseñar tus modelos con un tenant_id desde el primer momento. Esto permite migrar posteriormente a cualquier enfoque sin tener que reescribir la aplicación.
La mejor arquitectura multitenant es aquella que se adapta a tu situación actual. Una startup con 10 clientes que utiliza una base de datos por cliente está pagando 10 veces más de lo que debería.
— alokknight Ingeniería
