Cómo Construir un Sistema de Multi-Tenancy en Laravel desde Cero

24 May 2026 · 6 min · Arquitectura

Construir un sistema multi-tenant correctamente es uno de los retos arquitectónicos más importantes dentro del desarrollo SaaS moderno. Aunque Laravel facilita enormemente la construcción de aplicaciones web, implementar multi-tenancy de manera segura y escalable requiere mucho más que agregar un simple tenant_id en las tablas.

En aplicaciones pequeñas, una implementación básica puede parecer suficiente. Pero conforme crece la cantidad de clientes, usuarios y datos, los problemas empiezan a aparecer:

  • Filtraciones de información entre tenants.

  • Consultas inseguras.

  • Problemas de escalabilidad.

  • Complejidad en autenticación.

  • Migraciones difíciles de mantener.

  • Procesos de onboarding complicados.

Desde mi experiencia trabajando con arquitecturas Laravel, el éxito de un sistema multi-tenant depende principalmente de una decisión crítica tomada al inicio: cómo aislar los datos.

¿Qué es realmente multi-tenancy?

Un sistema multi-tenant es una arquitectura donde múltiples clientes o empresas comparten una misma aplicación, pero cada tenant mantiene sus datos completamente aislados.

Por ejemplo:

  • Un CRM SaaS.

  • Un sistema ERP empresarial.

  • Una plataforma educativa.

  • Software administrativo multiempresa.

Cada organización utiliza la misma infraestructura, pero nunca debe poder acceder a datos de otra organización.

En multi-tenancy, la seguridad no depende únicamente de permisos. Depende principalmente del aislamiento correcto de datos.

Los tres enfoques principales de multi-tenancy

Existen tres estrategias principales para construir sistemas multi-tenant.

1. Base de datos compartida

Todos los tenants comparten las mismas tablas utilizando un campo tenant_id.

Ejemplo:

users posts orders invoices

Cada tabla contiene:

tenant_id

Ventajas:

  • Infraestructura simple.

  • Menor costo operativo.

  • Migraciones centralizadas.

  • Backups más sencillos.

Desventajas:

  • Mayor riesgo de filtraciones.

  • Consultas más complejas.

  • Escalabilidad limitada.

  • Problemas en tenants enormes.

2. Base de datos por tenant

Cada tenant tiene su propia base de datos.

Este enfoque ofrece un aislamiento mucho más fuerte.

Ventajas:

  • Mayor seguridad.

  • Mejor aislamiento.

  • Escalabilidad independiente.

  • Backups individuales.

Desventajas:

  • Infraestructura más compleja.

  • Mayor costo operativo.

  • Migraciones distribuidas.

  • Administración más difícil.

3. Esquemas separados

Una estrategia intermedia consiste en usar múltiples schemas dentro de una misma base de datos.

Aunque técnicamente interesante, suele aumentar considerablemente complejidad operativa.

Mi enfoque recomendado

En la mayoría de proyectos SaaS medianos, considero que comenzar con base de datos compartida + aislamiento estricto suele ser la mejor decisión inicial.

Permite:

  • Desarrollo más rápido.

  • Menor costo.

  • Infraestructura simple.

  • Escalabilidad razonable.

Sin embargo, el sistema debe diseñarse desde el inicio pensando en una posible migración futura hacia bases separadas.

Identificando el tenant

Uno de los primeros retos es detectar correctamente qué tenant está realizando la request.

Las estrategias más comunes:

  • Subdominios.

  • Dominios personalizados.

  • Headers.

  • Path prefixes.

Por ejemplo:

empresa1.app.com empresa2.app.com

En Laravel:

Route::domain('{tenant}.app.com') ->group(function () { // rutas tenant });

Esto facilita resolver automáticamente el contexto del tenant.

Middleware de resolución de tenant

Una práctica fundamental es resolver el tenant dentro de middleware.

Por ejemplo:

class IdentifyTenant { public function handle($request, Closure $next) { $tenant = Tenant::where('slug', request()->route('tenant')) ->firstOrFail();app()->instance('tenant', $tenant);return $next($request); } }

Esto permite acceder globalmente al tenant actual:

app('tenant')

Centralizar esta lógica evita duplicación y mejora seguridad.

Global Scopes: aislamiento automático

Uno de los mecanismos más poderosos para multi-tenancy en Laravel son los Global Scopes.

Por ejemplo:

class TenantScope implements Scope { public function apply(Builder $builder, Model $model) { $builder->where('tenant_id', app('tenant')->id); } }

Y luego:

protected static function booted() { static::addGlobalScope(new TenantScope); }

Ahora todas las consultas quedan automáticamente aisladas.

Esto reduce enormemente el riesgo de olvidar filtros manuales.

El error más peligroso en multi-tenancy

Uno de los errores más comunes es confiar únicamente en:

where('tenant_id', auth()->user()->tenant_id)

disperso por toda la aplicación.

Esto eventualmente produce filtraciones accidentales.

La seguridad nunca debería depender de recordar agregar condiciones manualmente.

Autenticación y autorización

En sistemas multi-tenant, autenticación y autorización se vuelven mucho más delicadas.

Por ejemplo:

  • Usuarios perteneciendo a múltiples tenants.

  • Roles distintos según tenant.

  • Permisos dinámicos.

  • Invitaciones empresariales.

Mi recomendación general es separar:

  • Identity: quién es el usuario.

  • Membership: a qué tenant pertenece.

  • Permissions: qué puede hacer.

Esto crea una arquitectura mucho más flexible.

Procesamiento de queues y jobs

Otro problema frecuente aparece con queues.

Los jobs asíncronos deben conservar correctamente el contexto tenant.

Por ejemplo:

class ProcessInvoice implements ShouldQueue { public function __construct( public int $tenantId ) {} }

Antes de ejecutar lógica, el job debe restaurar el tenant actual.

Muchos bugs difíciles aparecen precisamente cuando procesos background pierden contexto.

Escalabilidad real

Con millones de registros y cientos de tenants, algunos problemas empiezan a crecer rápidamente:

  • Índices enormes.

  • Consultas lentas.

  • Bloqueos.

  • Contención de recursos.

Por eso es fundamental indexar correctamente:

tenant_id

Especialmente en:

  • Foreign keys.

  • Tablas transaccionales.

  • Logs.

  • Facturación.

Un índice mal diseñado puede destruir el rendimiento del sistema completo.

Particionado y separación futura

Los sistemas multi-tenant exitosos normalmente evolucionan con el tiempo.

Es común que tenants enormes eventualmente necesiten:

  • Base dedicada.

  • Infraestructura aislada.

  • Servidores propios.

Por eso recomiendo diseñar una capa de resolución de conexión desde el inicio.

Esto facilita migraciones futuras sin reescribir toda la aplicación.

Logs y auditoría

En aplicaciones multi-tenant, la trazabilidad es crítica.

Cada log debería incluir:

  • Tenant.

  • Usuario.

  • IP.

  • Acción.

  • Timestamp.

Esto simplifica debugging y análisis de incidentes de seguridad.

Testing en multi-tenancy

Muchos sistemas parecen funcionar correctamente hasta que aparecen bugs relacionados con aislamiento.

Por eso el testing multi-tenant debe validar:

  • Aislamiento de datos.

  • Permisos.

  • Acceso cruzado.

  • Queries filtradas.

  • Queues.

Las pruebas de seguridad son especialmente importantes.

¿Usar paquetes o construirlo manualmente?

Laravel tiene excelentes paquetes como:

  • Stancl Tenancy.

  • Spatie Multitenancy.

Para muchos proyectos son una gran solución.

Sin embargo, entender los principios internos sigue siendo fundamental.

Los paquetes ayudan a acelerar desarrollo, pero no reemplazan las decisiones arquitectónicas correctas.

Conclusión

Construir un sistema multi-tenant profesional en Laravel implica mucho más que agregar un campo tenant_id.

La verdadera dificultad está en:

  • Aislar correctamente datos.

  • Escalar consultas.

  • Manejar seguridad.

  • Conservar mantenibilidad.

  • Prepararse para crecimiento futuro.

En mi experiencia, las mejores arquitecturas multi-tenant son aquellas que priorizan simplicidad al inicio, pero dejan espacio suficiente para evolucionar conforme el negocio crece.

El reto real no es solamente compartir infraestructura. El reto es garantizar que cada tenant sienta que la plataforma fue construida exclusivamente para él.

Afiliado
Curado por José Luis Luna Rubio

Acelera tu perfil
técnico con
Platzi

Más de 240 cursos y 48 carreras para fortalecer desarrollo, producto, diseño y habilidades digitales con una ruta estructurada.

  • Rutas por carrera
  • Aprendizaje práctico
  • Formación continua
240+ Cursos
48 Carreras
1mes Gratis
Obtener 1 mes gratis

Enlace de afiliado — si entras desde aquí,
apoyas este sitio sin costo extra para ti.