Buenas Prácticas de Modelado de Datos
Modela el dominio, no la pantalla de la UI actual. Usa esta lista durante las revisiones de esquemas, los PR de migración y las actualizaciones de ADR.
Cómo Usar Esta Lista
- Recórrela de arriba a abajo para tablas nuevas (greenfield); usa secciones individuales para revisiones específicas.
- Registra las violaciones como tickets de migración con un propietario y una fecha límite.
- Revísala trimestralmente o después de cualquier incidente de corrupción de datos.
- Combínala con
EXPLAINy consultas de integridad: los errores de modelado se manifiestan como huérfanos (orphans) y uniones de tipo fan-out.
A - Fidelidad del Dominio
- Nombra las tablas según sustantivos del dominio, no etiquetas de pantalla.
checkout_summary_rowse convierte enorders+line_itemscuando cambia la UI. - Codifica invariantes en la base de datos. Usa restricciones
NOT NULL,CHECK,UNIQUEy de clave externa (FK), no solo validación de la aplicación. - Documenta la propiedad de la tabla en
COMMENT ON. Cada tabla de producción tiene un único servicio o equipo escritor. - Prefiere
timestamptzpara instantes. Almacena en UTC; convierte al mostrar. Evitatimestamp without time zonepara eventos de usuario. - Usa claves de identidad
bigintsustitutas para OLTP. Las claves naturales pertenecen a restriccionesUNIQUEcuando están garantizadas por el negocio.
B - Relaciones y Cardinalidad
- Resuelve las relaciones de muchos a muchos con tablas de unión. Nunca dupliques columnas de etiquetas (
tag1,tag2) en una tabla de hechos. - Indexa cada columna de clave externa. Las FK sin indexar causan uniones lentas y cascadas costosas al eliminar.
- Haz explícita la opcionalidad. Padre requerido: FK
NOT NULL; opcional: FK anulable másLEFT JOINen las consultas. - Elige
ON DELETEdeliberadamente.CASCADE,RESTRICTySET NULLdeben coincidir con las reglas de negocio, no con los valores predeterminados. - Evita FKs entre contextos a menos que los equipos implementen juntos. Prefiere referencias UUID lógicas entre contextos delimitados (bounded contexts).
C - Diseño Físico de PostgreSQL
- Mapea contextos delimitados a esquemas. Evita que
publicse convierta en un cajón de sastre compartido. - Otorga el mínimo privilegio por rol de aplicación. Los servicios no deben hacer
UPDATEen tablas que no poseen. - Planifica la evolución del esquema con expandir-contraer. Añade columnas y vistas de compatibilidad antes de eliminar formas antiguas.
- Captura precios y etiquetas en filas transaccionales.
order_items.unit_priceno debe cambiar cuando cambie el precio del catálogo. - Valida las convenciones de nomenclatura en CI.
snake_caseconsistente, tablas plurales y sufijos_idagilizan las revisiones.
D - Operaciones y Longevidad
- Registra ADRs para la topología de la base de datos. Las decisiones de base de datos compartida única vs. por servicio necesitan una fecha de revisión.
- Prueba las migraciones en una copia de las estadísticas de producción. Las estimaciones de cardinalidad afectan las opciones de índices y particiones.
- Mide antes de desnormalizar. Demuestra el dolor de lectura con
pg_stat_statements; documenta las invariantes de actualización si desnormalizas. - Ejecuta consultas de detección de huérfanos después de rellenos (backfills).
LEFT JOIN ... WHERE parent IS NULLdebería devolver cero filas. - Da de baja las vistas de compatibilidad en un calendario. Las vistas sin fechas de finalización se convierten en basura permanente.
Preguntas Frecuentes
¿Por qué modelar el dominio en lugar de la UI?
Las pantallas cambian semanalmente; las reglas del dominio (un pedido tiene artículos, un usuario tiene un email) duran años. Las tablas con forma de UI requieren migraciones dolorosas cuando cambia la navegación.
¿Cuál es la barra mínima de integridad para una nueva tabla?
Clave primaria, created_at timestamptz, comentario de propiedad y restricciones para cada regla de negocio que puedas nombrar en una frase.
¿Cuándo debería desnormalizar?
Después de que el diseño normalizado esté en producción y pg_stat_statements demuestre que el costo de las uniones bloquea los SLOs. Documenta qué debe mantenerse sincronizado y cómo detectas la deriva.
¿Cómo impongo la propiedad con múltiples servicios?
Esquemas separados, roles de base de datos separados, lista de verificación de revisión de código y, opcionalmente, REVOKE de INSERT/UPDATE entre esquemas para los roles de aplicación.
¿Debería cada columna tener un comentario?
Comenta tablas y columnas no obvias (enums de estado, flags de borrado lógico, suposiciones de moneda). Omite el ruido a nivel de id.
¿Cuál es el principal error de modelado en SaaS?
Olvidar tenant_id en tablas hijas o índices que comienzan con tenant_id, lo que causa fugas entre inquilinos y consultas lentas.
¿Cómo reviso un PR que añade una columna JSONB?
Pregunta: ¿qué campos necesitan integridad de FK, indexación y restricciones CHECK? JSON no estructurado es un área de preparación, no un esquema de destino.
¿Cuándo son aceptables los tipos ENUM de PostgreSQL?
Conjuntos cerrados que cambian raramente y con una cadencia de lanzamiento lenta. Prefiere text + CHECK cuando el producto añade valores frecuentemente.
¿Cómo encajan las vistas en las buenas prácticas de modelado?
Usa vistas de compatibilidad versionadas para la estabilidad de la API durante las migraciones. No permitas que las aplicaciones consulten vistas ad-hoc en lugar de tablas propias sin documentación.
¿Qué debo llevar a una revisión de arquitectura?
ERD o lista de tablas, matriz de propiedad, plan de expansión-contracción de migración y una consulta que demuestre la existencia del índice de la ruta crítica.
Relacionado
- Conceptos Básicos de Modelado de Datos - ejemplos introductorios
- Modelado Entidad-Relación - referencia de cardinalidad
- Límites de Esquema Basados en Dominio - límites de esquema
- Estrategia de Evolución de Esquemas - cambio seguro a lo largo del tiempo
- Conceptos Básicos de Normalización - prevención de anomalías
Versiones de Stack: Esta página fue escrita para PostgreSQL 18.4 (estable 18, mantenimiento 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x y PostGIS 3.5+.