Desarrollo de plataformas SaaS
Desarrollo de SaaS multiinquilino con Laravel
La decisión de aislamiento se toma una vez y decide todo lo demás - qué cuesta un cliente ruidoso a sus vecinos, y si la revisión de seguridad de una gran cuenta acaba la conversación.
Todo producto multiinquilino toma pronto una decisión que luego no deshace fácilmente: dónde está el muro entre clientes. Todo lo demás —cuánto cuesta una caída, cuánto tarda una restauración, si una revisión de seguridad de una gran cuenta sale bien— se deriva de ahí.
La decisión se suele tomar de forma implícita, por quien añade la primera
columna company_id, y se descubre dos años después cuando empieza a doler.
Los tres modelos, y a quién le sirve cada uno
Un esquema, una columna de inquilino en cada tabla. El más barato de construir y de operar. Una base de datos, una migración, un pool de conexiones. Le sirve a productos con muchas cuentas pequeñas y ningún cliente lo bastante grande como para exigir otra cosa.
Su debilidad es que el aislamiento es una propiedad de su código y no de la infraestructura. Un filtro que falta es una brecha de datos, una restauración para un cliente significa extraer sus filas de una copia de seguridad de todos, y la consulta pesada de un inquilino ruidoso la sienten todos.
Una base de datos por inquilino. Aislamiento que se puede señalar con el dedo en una revisión de seguridad. La copia y la restauración son por cliente, una solicitud de supresión es una base de datos eliminada, y los requisitos de residencia se satisfacen por cuenta.
El coste es operativo y es real: las migraciones se ejecutan N veces y pueden fallar en la nonagésimo cuarta, las conexiones se multiplican, y «cuántos inquilinos tenemos» pasa a ser una pregunta sobre infraestructura y no un recuento.
Ambos, por nivel. Compartido por defecto, dedicado para quien lo pague. Es lo que acaban ejecutando la mayoría de los productos con éxito, y construir para ello desde pronto cuesta poco si la frontera del inquilino es explícita: la aplicación pide una conexión en lugar de suponerla.
Qué construimos en cualquier caso
Un inquilino resuelto una vez, en el borde. A partir del dominio, del subdominio o del usuario autenticado, en un solo sitio y pronto en la petición, para que nada más abajo tenga que volver a averiguarlo. Los trabajos lo llevan de forma explícita, porque un trabajo en cola no tiene petición de la que leerlo, y ahí es donde nacen de verdad los fallos entre inquilinos.
Aislamiento aplicado por el modelo, no por la disciplina. Un scope global
hace que una cláusula where olvidada devuelva nada en lugar de todo. Junto a
una factory consciente del inquilino y pruebas que afirman que el registro de
otro inquilino es invisible, la garantía sobrevive al desarrollador que entre
el año que viene.
Colas que no puedan matarse de hambre unas a otras. Un cliente importando dos millones de filas no debe retrasar el restablecimiento de contraseña de todos los demás. Eso es disposición de colas y workers —tratada en ingeniería de colas— y es la queja más habitual por la que nos llaman en plataformas SaaS que crecen más allá de sus primeros cientos de cuentas.
Cachés y almacenamiento con clave por inquilino. Las claves de caché, los archivos subidos y los documentos generados también necesitan la frontera. Una clave de caché que omite al inquilino es la fuga de datos más rápida posible y la más difícil de notar.
Alta y baja como código. Crear un inquilino —esquema, datos iniciales, dominio, facturación— debería ser una operación y no un manual. Eliminarlo también, incluido lo que diga el contrato sobre retención.
La facturación, donde se filtra el esquema
La facturación por suscripción parece una integración y se comporta como un problema de modelado. Los planes cambian, los clientes suben de nivel a mitad de periodo, las pruebas se alargan, un pago falla tres días después de que se usara la funcionalidad.
Dos decisiones ahorran la mayor parte del dolor. Los derechos de uso son un concepto propio en lugar de leerse del proveedor de pagos: la aplicación pregunta si este inquilino puede hacer esto, no cuál es su estado en Stripe. Y el histórico de facturación es inmutable: una subida de nivel escribe un registro nuevo en lugar de editar el viejo, porque la factura que emitió en marzo tiene que seguir diciendo lo que decía.
Dónde encaja esto
Esto es desarrollo de aplicaciones con las decisiones de multiinquilinidad tomadas a propósito. Si la plataforma ya existe y la dificultad es que la carga de un cliente es el problema de todos, eso es rendimiento y escalado. Y si la dificultad es que nadie está seguro de que el aislamiento aguante de verdad, la auditoría responde exactamente a eso, con las consultas que lo demuestran en un sentido o en el otro.
Cómo transcurre un encargo
Empieza con una pregunta contestada sobre papel: cuál de los tres modelos de inquilinos necesita este producto, y qué va a exigir probablemente un contrato con su mayor cliente futuro.
El alcance que sigue fija el modelo, las garantías de aislamiento, el comportamiento de la facturación y las fases, con un precio. Se firma antes de construir nada de ello, porque el multi-inquilino es la única decisión de esta página que no se puede cambiar después sin un proyecto de migración propio.
Después el desarrollo, en fases que terminan desplegadas, con las pruebas de aislamiento escritas junto a las funcionalidades.
Qué recibe
El modelo de inquilinos se escribe antes de construir nada, luego la aplicación con el aislamiento aplicado en la capa de datos, y una suite de pruebas cuyos casos negativos son el objetivo. Un inquilino que no puede leer las filas de otro, comprobado y no supuesto.
Con ello, la conciliación de la facturación, la ruta de migración entre los tres modelos por si eligió el equivocado, y una respuesta escrita a la pregunta que todo comprador corporativo acaba haciendo sobre dónde están sus datos y quién puede llegar a ellos.
