Probablemente hayas visto las demos de los generadores de código impulsados por AI. Escribes un prompt como “construye un SaaS de gestión de proyectos multi-tenant” y, unos minutos después, tienes un panel precioso, un router de frontend y un esquema de base de datos generado en segundo plano. Parece increíblemente rápido, pero en cuanto miras bajo el capó - especialmente el esquema de la base de datos - la magia empieza a mostrar sus costuras.
Los modelos de lenguaje extensos (LLM) son excelentes prediciendo texto y escribiendo componentes de interfaz, pero no entienden el álgebra relacional. Cuando un agente de AI monta una base de datos, optimiza el camino más corto para renderizar un elemento visual. El resultado es casi siempre una colección de tablas planas, desnormalizadas y frágiles que se romperán en el momento en que cargues datos reales de producción.
Si estás construyendo una aplicación con generadores de código modernos como Bolt o Lovable, no puedes permitir que la AI tome decisiones arbitrarias sobre la base de datos. Tienes que guiarla. Puedes escribir prompts que obliguen a la AI a respetar las reglas clásicas de bases de datos, manteniendo tus esquemas relacionales limpios y protegiendo la integridad de tus datos.
Por qué los LLM fallan en el diseño de bases de datos relacionales
Los motores de bases de datos operan bajo una teoría de conjuntos matemática y estricta. Para evitar anomalías de datos, conflictos de actualización y consultas lentas, una base de datos requiere un modelo relacional estructurado. Los LLM, por el contrario, operan basándose en la probabilidad semántica. Escriben esquemas basándose en lo que parece visualmente plausible en el código, lo que introduce tres fallos arquitectónicos comunes.
La trampa de la tabla plana desnormalizada
A las herramientas de AI no les gusta crear tablas de unión. Para un LLM es mucho más fácil crear una única tabla de users y meter una lista de etiquetas separadas por comas directamente en un campo de texto que configurar una tabla de unión adecuada. Cuando tu frontend necesita filtrar usuarios por sus etiquetas, la AI escribe expresiones regulares complejas y sin indexar para analizar ese campo de texto. Este enfoque funciona bien con tres registros de prueba en el navegador, pero colapsará la CPU de tu base de datos en cuanto tu base de usuarios crezca.
Omitir las restricciones
En una base de datos relacional, las restricciones son tu última línea de defensa. Evitan registros vacíos, garantizan correos electrónicos únicos y aseguran que al borrar un registro padre se limpien sus registros hijos. Como las restricciones requieren una configuración lógica estricta, los generadores de AI suelen omitirlas. Crean tablas sin claves primarias, omiten los flags NOT NULL en campos obligatorios e ignoran por completo las claves foráneas. Esto hace que la base de datos sea muy frágil, y un solo error en la capa de aplicación puede corromper todo tu conjunto de datos.
Derivación del esquema y bucles de regresión
Si dejas que tu constructor de AI genere cambios en la base de datos de forma incremental mientras modificas visualmente el frontend, pronto te encontrarás con una derivación del esquema (schema drift). La AI escribirá un nuevo archivo de migración que entra en conflicto con tus tablas existentes, borrará columnas con datos reales para resolver un conflicto de renombramiento o creará tablas redundantes para dar soporte a un nuevo componente visual.
Para evitar estos problemas, debes imponer las reglas de las bases de datos relacionales desde el primer prompt.
Regla 1: Imponer la Tercera Forma Normal (3NF)
Para mantener tus datos limpios y que las consultas sean rápidas, tus tablas deben estar normalizadas. La normalización es el proceso de organizar los datos para minimizar la redundancia y la dependencia. En una aplicación profesional, deberías aspirar a la Tercera Forma Normal (3NF).
Para obtener tablas normalizadas de una IA, debes definir explícitamente cómo debe manejar los atributos:
- Primera Forma Normal (1NF): Cada columna debe contener valores atómicos (indivisibles). La IA nunca debe guardar listas separadas por comas, arrays JSON o cadenas semiestructuradas dentro de un único campo de la base de datos.
- Segunda Forma Normal (2NF): Todos los atributos que no sean claves deben depender totalmente de la clave primaria. Si una tabla tiene una clave compuesta, cada columna debe relacionarse con la clave completa, no solo con una parte.
- Tercera Forma Normal (3NF): Ninguna columna debe depender de otra columna que no sea clave (sin dependencias transitivas). Por ejemplo, si tienes una tabla
projects, no guardes el nombre y el teléfono del cliente directamente en ella. El proyecto debe vincularse a una tablaclientsmediante una clave foránea, y los detalles del cliente deben residir allí.
Plantilla de prompt para la normalización
Al inicializar una base de datos mediante SQL DDL o al dar instrucciones a tu AI builder, utiliza una regla de sistema explícita:
“Al generar el esquema de la base de datos relacional, diseña todas las tablas en Tercera Forma Normal (3NF). No utilices arrays JSON, columnas JSONB ni campos de texto separados por comas para almacenar atributos o relaciones multivaloradas. En su lugar, extráelos en tablas hijas normalizadas o tablas intermedias (junction tables) con restricciones de clave foránea. Asegúrate de que los atributos que no sean claves dependan estrictamente de la clave primaria, evitando las dependencias transitivas.”
Al obligar a la IA a trabajar bajo estas restricciones, evitas que tome atajos para ahorrar esfuerzo de desarrollo en la parte de la interfaz de usuario.
Regla 2: Define explícitamente las restricciones de integridad de datos
Una base de datos sin restricciones es una bomba de tiempo. Si quieres una base de datos que se mantenga limpia y consistente, debes instruir a la IA para que escriba reglas explícitas directamente en la definición del esquema SQL.
Claves primarias y foráneas
Exige siempre que cada tabla tenga una única clave primaria claramente definida. Para las aplicaciones web modernas, se suelen preferir los UUID frente a los enteros autoincrementales, ya que evitan los ataques de enumeración de IDs y permiten generar IDs de forma segura en el cliente antes de escribirlos en la base de datos.
Además, cada relación debe utilizar claves foráneas explícitas. Si una tabla tasks tiene un campo project_id, ese campo debe apuntar directamente a la tabla projects. También debes instruir a la IA para que especifique el comportamiento al eliminar:
- Usa
ON DELETE CASCADEsi el registro hijo debe eliminarse cuando se elimine el padre (por ejemplo, al borrar un proyecto deberían borrarse sus tareas). - Usa
ON DELETE RESTRICToON DELETE SET NULLsi los registros hijos deben permanecer intactos (por ejemplo, borrar un usuario no debería borrar el historial de logs de equipo que haya escrito).
Restricciones Not Null, Unique y Check
No permitas que la IA cree columnas que acepten valores NULL por defecto, a menos que el campo sea realmente opcional. Los campos de email, nombres de usuario e IDs de organización siempre deben definirse como NOT NULL.
Las restricciones de unicidad (Unique) deben configurarse explícitamente en campos como emails, tokens o slugs personalizados. Por último, las restricciones de comprobación (CHECK) son muy útiles para evitar estados de datos inválidos antes de que lleguen a tus tablas. Por ejemplo, una columna status debería estar restringida a una lista específica de cadenas (como pending, active o archived).
Plantilla de prompt para la integridad
Incorpora estas reglas en tu flujo de generación:
“Para cada tabla de la base de datos, debes definir una clave primaria usando UUIDs. Cada relación debe imponerse con una restricción de clave foránea, indicando explícitamente la política de eliminación (usa CASCADE para subrecursos dependientes, y RESTRICT o SET NULL para entidades independientes). Aplica NOT NULL a todos los campos obligatorios. Usa restricciones UNIQUE para las columnas de identificación única y restricciones CHECK para limitar las columnas de estado a conjuntos de cadenas válidos.”
Regla 3: Diseña tablas intermedias relacionales
Las relaciones de muchos a muchos son un punto de fallo común en los generadores de IA. Si los usuarios pueden pertenecer a varios espacios de trabajo, o los proyectos pueden tener varias etiquetas, necesitas una tabla intermedia (junction table) para conectarlos.
Una tabla intermedia correcta debe contener:
- Una clave foránea que apunte a la primera tabla.
- Una clave foránea que apunte a la segunda tabla.
- Una clave primaria compuesta por ambas claves foráneas para evitar relaciones duplicadas.
- Reglas de eliminación en cascada para que, al eliminar un usuario o espacio de trabajo, se limpie automáticamente el registro intermedio.
Cuando le pidas cosas a tu IA, a menudo intentará saltarse esta estructura porque gestionar los joins en componentes de React requiere un poco más de código frontend. Debes resistirte a esto. Obliga a la IA a usar tablas intermedias y deja que escriba las consultas relacionales (usando sentencias JOIN en SQL o consultas relacionales en las librerías cliente de Supabase) para cargar los datos.
El flujo de trabajo del constructor pragmático: Primero el esquema
Para mantener el control total de tu aplicación, debes separar el diseño de la base de datos del desarrollo del frontend. Dejar que una IA escriba el esquema de tu base de datos mientras diseña tus botones es una receta para entrar en bucles de regresión.
En su lugar, sigue este flujo de trabajo:
- Diseña el esquema primero: Pide a la IA que escriba un archivo SQL DDL puro basado en las reglas que hemos descrito.
- Revisa el SQL manualmente: Asegúrate de que cada tabla esté normalizada, las restricciones estén definidas y los índices estén configurados en las claves foráneas.
- Ejecuta las migraciones: Ejecuta el script SQL directamente en tu editor de base de datos (como el editor SQL de Supabase).
- Importa el esquema en tu constructor: Una vez que las tablas estén activas en tu base de datos, pide a tu AI builder (como Lovable o Bolt) que lea el esquema existente en lugar de generar uno nuevo.
Este enfoque de “primero el esquema” garantiza que tu base de datos se mantenga limpia, estándar y totalmente estructurada, incluso cuando la IA escriba el código del frontend.
Una alternativa: No-code estructurado sin la carga de una base de datos
Gestionar migraciones SQL, restricciones de clave foránea y estructuras normalizadas requiere mucho esfuerzo de desarrollo, incluso con ayuda de la IA. Si estás creando herramientas internas de negocio, directorios o portales de clientes, no siempre necesitas gestionar una base de datos Postgres pura.
Aquí es donde los constructores visuales estructurados como Softr ofrecen un enfoque diferente. En lugar de escribir SQL DDL, puedes conectar tu aplicación directamente a plataformas de datos estructurados como Airtable, Google Sheets o SmartSuite.
Este modelo ofrece varias ventajas claras:
- Gestión visual de relaciones: Puedes configurar campos relacionales (como vincular un cliente a un proyecto) visualmente en tu fuente de datos, sin preocuparte por tablas intermedias de SQL o políticas de eliminación de claves foráneas.
- Permisos de usuario granulares: Softr gestiona los permisos y roles de usuario visualmente en el editor, lo que significa que no tienes que escribir políticas de seguridad de base de datos complejas (como Row Level Security de Postgres) para mantener privados los datos del cliente.
- Desarrollo predecible: Como estás configurando componentes preconstruidos en lugar de pedirle a un LLM que regenere código, evitas los bucles de regresión que afectan a las apps generadas. Puedes cambiar el diseño o añadir nuevos campos a la base de datos sin riesgo de romper las consultas existentes.
Si necesitas un MVP de SaaS altamente personalizado con computación compleja en segundo plano, diseñar esquemas de base de datos para un backend de Postgres es un gran camino. Pero si necesitas desplegar una herramienta operativa, usar una herramienta estructurada como Softr te ahorrará horas de mantenimiento de base de datos.