Al construir una aplicación SaaS, una de las primeras decisiones arquitectónicas que debes tomar es cómo manejar el multi-tenancy. Necesitas asegurarte de que los datos del Cliente A estén estrictamente aislados del Cliente B, mientras mantienes bajos los costos de infraestructura y la carga operativa.
La explosión combinatoria de modos de fallo en el sharding tradicional de bases de datos puede hacer imposible anticipar cada escenario con automatización estática y manual. Un enfoque moderno implica aprovechar Postgres Serverless y la separación lógica.
Por qué la fragmentación estática se rompe a escala
Los sistemas tradicionales de auto-remediación a menudo operan como máquinas de estados de un solo paso, codificadas rígidamente. Si un shard falla, un conjunto de scripts se ejecuta en una secuencia cuidadosamente ordenada para arreglar votos, ajustar prioridades o reconstruir un nodo caído.
Esto funciona bien para casos simples, pero tiene limitaciones fundamentales:
- Las dependencias implícitas significan que el ordenamiento es frágil.
- Los escenarios de múltiples fallos exponían puntos ciegos. Cuando múltiples nodos afectados se combinan con particiones de red, la lógica estática puede entrar en un bucle infinito.
El salto a Postgres Serverless con Neon
Para solucionar esto, los desarrolladores están migrando cada vez más sus capas de enrutamiento principales a soluciones de Postgres Serverless como Neon. En lugar de gestionar fragmentos físicos (shards) y lidiar con el reequilibrio manual, puedes aprovechar la separación de almacenamiento y cómputo.
Esto te permite construir una verdadera arquitectura multi-tenant usando dos conceptos clave:
1. Seguridad a Nivel de Fila (RLS) para el aislamiento de Inquilinos
En lugar de aprovisionar una nueva base de datos para cada cliente (lo que escala mal y aumenta los costos de infraestructura), agrupas a los inquilinos en bases de datos compartidas. Impones un estricto aislamiento de datos utilizando la Seguridad a Nivel de Fila de Postgres (RLS).
Cada consulta ejecutada por tu API puede estar envuelta en una transacción que establece una variable local para el tenant_id. Postgres automáticamente añade WHERE tenant_id = current_setting('app.current_tenant') a cada lectura y escritura. Incluso si hay un error en la lógica de tu aplicación, un inquilino no puede ver los datos de otro.
2. Agrupación de conexiones en el Edge (Connection Pooling)
Un gran desafío con Postgres es el agotamiento de las conexiones. Si 5,000 inquilinos se conectan simultáneamente, Postgres fallará. Puedes solucionar esto implementando PgBouncer en el borde, escalándolo en múltiples regiones y enrutando dinámicamente las consultas a los puntos finales de cómputo.
El Resultado
Al migrar a esta arquitectura, puedes reducir drásticamente la carga operativa. Ya no necesitas despertarte de madrugada para arreglar shards rotos porque el cómputo escala instantáneamente según la carga, y el almacenamiento se gestiona de forma transparente por el proveedor de la nube.