Explica cómo asignar ownership de datos, escrituras, invariantes y modelos de lectura para evitar bases compartidas sin autoridad y acoplamiento entre contextos.
Última actualización
Actualizada
Nivel
Aplicación
La arquitectura de persistencia no empieza preguntando qué base de datos usar. Empieza identificando quién posee cada dato, qué invariantes deben protegerse, cómo se consulta la información y qué ocurrirá cuando el modelo evolucione o falle una dependencia.
Los datos no son un recurso neutral compartido por toda la aplicación. Representan decisiones de negocio, estados con significado y reglas que alguien debe proteger.
Cuando varios módulos pueden leer y escribir las mismas tablas sin contrato, el esquema termina funcionando como una API implícita. Cualquier cambio requiere coordinación global y las invariantes quedan repartidas entre servicios, jobs, scripts y reportes.
La arquitectura de persistencia busca responder cuatro preguntas:
¿Quién es la autoridad sobre este dato?
¿Qué operaciones pueden modificarlo?
¿Qué garantías deben conservarse durante concurrencia y fallo?
¿Cómo acceden otros consumidores sin apropiarse del modelo interno?
Una forma útil de pensar los datos es distinguir autoridad de representación.
Texto
fuente de verdad
→ posee reglas e invariantes
→ acepta modificaciones válidas
copias o proyecciones
→ optimizan lectura o integración
→ pueden reconstruirse
→ no redefinen la verdad
Por ejemplo:
Inventario es autoridad sobre disponibilidad y reservas.
Pedidos conserva una copia del resultado de reserva necesario para su flujo.
Analítica mantiene una proyección histórica para consultas.
La duplicación no siempre es incorrecta. Es peligrosa cuando no se sabe cuál copia manda ni cómo reconciliar divergencias.
Ownership significa responsabilidad completa, no solo ubicación de tablas.
El propietario debe definir:
Modelo y semántica.
Invariantes.
Operaciones permitidas.
Política de compatibilidad.
Migraciones.
Seguridad y retención.
Backups y recuperación.
Señales operativas.
Ruta para corregir datos inconsistentes.
En un monolito modular, varios módulos pueden usar la misma instancia PostgreSQL y seguir teniendo ownership separado mediante schemas, permisos, repositorios y reglas de dependencia.
En un monolito, una vista de base o función puede exponer datos sin permitir escritura ni conocimiento de internals. Sigue siendo un contrato que debe versionarse.
Una transacción debe cubrir las modificaciones que necesitan consistencia inmediata. Si confirmar un pedido exige que estado, líneas y total cambien juntos, pertenecen a una frontera transaccional coherente.
No todo dato relacionado debe estar dentro de la misma transacción. Inventario y Pedidos pueden tener ownership distinto si el negocio acepta un proceso con reserva, confirmación y compensación.
Texto
una transacción local
→ garantía fuerte dentro del propietario
varios propietarios
→ coordinación, estados intermedios y convergencia
La decisión depende de las invariantes, no de una preferencia por microservicios.
Una opción dentro de un monolito modular es usar una transacción coordinada localmente si ambos módulos viven en el mismo proceso y la invariante lo requiere.
Otra opción es separar propietarios:
Texto
Orders: pending_stock
→ solicita reserva
Inventory: reserved / rejected
→ responde o publica resultado
Orders: confirmed / rejected
Esta segunda opción admite autonomía, pero añade estados intermedios, timeout, idempotencia y reconciliación. No es “más moderna”; compra una capacidad concreta a cambio de complejidad.
Las consultas analíticas suelen necesitar datos de varios dominios. Permitir que herramientas de BI golpeen directamente tablas operacionales crea acoplamiento y riesgo de rendimiento.
Alternativas:
Read replicas.
Data warehouse.
Eventos o CDC.
Proyecciones específicas.
Exports programados.
El pipeline debe conservar lineage, clasificación y reglas de retención.
Eliminar una fila principal no garantiza eliminación de cachés, índices, archivos, logs o backups. La arquitectura debe conocer todas las representaciones.
SQL vs NoSQL y elección de base de datos utiliza ownership, invariantes y patrones de acceso para decidir qué capacidades de almacenamiento necesita cada parte del sistema.