Construir un SaaS multi-tenant en Laravel: la serie que me habría gustado leer primero: 01 de 08

Por qué escribo una serie sobre diseñar y entregar un SaaS multi-tenant en Laravel: qué haría distinto desde el primer día, qué cubre la serie, a quién va dirigida y cómo leerla.

Construir un SaaS multi-tenant en Laravel: la serie que me habría gustado leer primero: 01 de 08
Photo by Austin Distel / Unsplash
Por qué escribo una serie sobre diseñar y entregar un SaaS multi-tenant en Laravel: qué haría distinto desde el primer día, qué cubre la serie, a quién va dirigida y cómo leerla.

Este es el artículo que habría querido leer antes de empezar a construir un sistema multi-tenant. Me habría ahorrado tiempo, mucho código reescrito y muchas horas migrando sistemas que ya estaban en marcha.

La mayoría de las decisiones caras en un SaaS multi-tenant son baratas el día uno y costosas el día cuatrocientos. Dónde vive el tenant en el schema, cómo una petición encuentra su empresa, qué sabe un job en segundo plano sobre para quién trabaja: cada una se puede resolver bien en una tarde al principio, o arreglar después con una migración, una reescritura y un deploy con los nervios de punta. Conozco el segundo camino porque lo he recorrido. Esta serie es lo que haría el primer día si empezara de nuevo, sabiendo lo que sé ahora.

Aquí va uno de esos caminos. Empecé multi-tenant, pero no multiusuario. Añadir el multiusuario después no fue una funcionalidad. Fue una reescritura que tocó todo el sistema. Y las guardas que mantienen los datos de un tenant lejos de otro no estaban tan bien construidas como debían. Los dos problemas están en los cimientos, y por eso el primer artículo de la serie trata de quién pertenece a qué empresa y cómo lo descubre una petición.

Qué es esta serie

Es un conjunto de decisiones con sus razones adjuntas, escrito para desarrolladores que ya construyen con Laravel y quieren diseñar y entregar un SaaS multi-tenant sin aprender las partes difíciles por el camino lento. Cada artículo sigue el mismo producto ficticio, una app de facturación donde el tenant es una Company, de modo que los ejemplos conectan de uno a otro.

No es una guía de paquetes, y no es un framework. No encontrarás una librería que instalar que te resuelva el tenancy. Encontrarás las piezas que creo que vale la pena construir tú mismo, por qué, y qué cuesta cada una. Donde una decisión es cuestión de criterio, lo digo.

Qué asume

Unas pocas elecciones están fijadas para que la serie pueda ir en profundidad y no en extensión:

  • Una aplicación Laravel y una base de datos, con una columna company_id en las tablas que pertenecen a un tenant. Si todavía decides entre un monolito modular y microservicios, esa es otra pregunta, y escribí sobre cómo abordarla en Monolito modular o microservicios: un marco para decidir sin dogmas.
  • Laravel 13 y PostgreSQL en los ejemplos, aunque casi todo aplica a otras versiones y a MySQL. El único artículo que depende de PostgreSQL lo dice desde el principio.
  • Un lector con algo de experiencia. No explico qué es un middleware ni una cola.

Lo que se deja fuera a propósito: una base de datos separada por tenant, el single sign-on y los detalles de cualquier proveedor de pagos concreto. Cada uno merece su propia serie, y ninguno es donde suele doler una primera versión.

Qué encontrarás

Estos son los artículos en el orden en que yo los leería. Cada uno se sostiene solo una vez que conoces el contexto del tenant del primero. Actualizo esta lista a medida que se publica la serie: un título con enlace ya está publicado, y un título sin enlace está por llegar.

  1. SaaS multi-tenant en Laravel: una base de datos, un global scope y las fugas que no detecta. El cimiento: cómo una petición encuentra su empresa, un scope que falla cerrado y lo que el scope todavía no ve.
  2. Adiós a los controladores gordos en Laravel: las Actions como hogar de la lógica de negocio. Dónde viven las reglas, para que un controlador, un comando y una API compartan una sola implementación.
  3. Data objects, Concerns y Events: el reparto de apoyo de una Action en Laravel. Qué alimenta a una Action, qué comparte y qué anuncia, con el contexto de tenant llevado a los listeners en cola.
  4. De la idea al primer cliente de pago: una hoja de ruta de entrega para un SaaS multi-tenant en Laravel. El orden del trabajo: muros antes que habitaciones, un slice temprano, límites de plan, webhooks de facturación y deploys seguros.
  5. Probar el aislamiento entre tenants en Laravel: tests de fuga, tests de guarda y lo que aún no detectan. Cómo demostrar, en cada commit, que una empresa no puede ver a otra.
  6. Observabilidad por tenant en Laravel: logs, métricas y errores por empresa. Cómo responder "¿qué le pasó a esta empresa?" sin ahogarte en datos.
  7. Row-Level Security en PostgreSQL: un segundo muro para una app Laravel multi-tenant. Una capa opcional a nivel de base de datos detrás del scope de la aplicación, y los casos en que vale su costo.

Cómo leerla

Dos hábitos ayudarán. Primero, trata el código como un punto de partida. Los fragmentos son pequeños a propósito, y no los he ejecutado contra tu schema, tus policies ni tu configuración de deploy. Segundo, presta atención a las secciones de costos. Cada patrón de aquí tiene un precio, y la pregunta honesta no es "¿es esto una buena práctica?" sino "¿vale la pena para mi equipo, a mi tamaño, este año?".

A veces la respuesta es que no. Una Action de paso, un Data object para dos argumentos o una política de base de datos para un prototipo son formas de gastar un esfuerzo que necesitabas en otro sitio.

Conclusión

Escribo esta serie porque el consejo más útil que puedo darle a mi yo del pasado es también el que la mayoría de los equipos oye demasiado tarde: decide los cimientos pronto, hazlos comprobables y mantén aburrido todo lo demás. Si estás a punto de empezar un producto multi-tenant, o estás lo bastante al principio como para que los cimientos aún puedan cambiar, empieza por el contexto del tenant. Todo lo demás de la serie se apoya en él.