22 oct 2025·8 min de lectura

Evolución de esquema segura ante regeneración para migraciones predecibles

La evolución de esquema segura ante regeneración mantiene los datos de producción válidos cuando se regenera el código del backend. Aprende una manera práctica de planificar cambios de esquema y migraciones.

Evolución de esquema segura ante regeneración para migraciones predecibles

Por qué los cambios de esquema parecen arriesgados con backends regenerados

Cuando tu backend se regenera a partir de un modelo visual, un cambio en la base de datos puede sentirse como tirar de un hilo en un suéter. Actualizas un campo en el Data Designer, haces clic en regenerar, y de repente no solo cambias una tabla. También cambias la API generada, las reglas de validación y las consultas que usa tu app para leer y escribir datos.

Lo que suele fallar no es que el nuevo código no compile. Muchas plataformas sin código (incluyendo AppMaster, que genera código Go real para backends) generarán un proyecto limpio cada vez. El verdadero riesgo es que ya existen datos en producción, y no se reconfiguran automáticamente para coincidir con tus nuevas ideas.

Las dos fallas que la gente nota primero son simples:

  • Lecturas rotas: la app ya no puede cargar registros porque una columna se movió, cambió el tipo o una consulta espera algo que no está.
  • Escrituras rotas: nuevos registros o actualizaciones fallan porque cambiaron restricciones, campos obligatorios o formatos, y los clientes existentes siguen enviando la forma antigua.

Ambas fallas son dolorosas porque pueden permanecer ocultas hasta que usuarios reales las encuentran. Una base de staging puede estar vacía o fresca, así que todo parece bien. Producción tiene casos límite: nulls donde asumiste valores, cadenas de enum antiguas o filas creadas antes de que existiera una regla nueva.

Por eso importa la evolución de esquema segura ante regeneración. El objetivo es hacer cada cambio seguro incluso cuando el código del backend se regenere por completo, de modo que los registros antiguos sigan siendo válidos y los nuevos puedan crearse.

"Migraciones predecibles" solo significa que puedes responder cuatro preguntas antes de desplegar: qué cambiará en la base de datos, qué pasará con las filas existentes, qué versión de la app puede seguir funcionando durante el despliegue y cómo revertirás si aparece algo inesperado.

Un modelo simple: esquema, migraciones y código regenerado

Cuando tu plataforma puede regenerar el backend, ayuda separar tres cosas en la cabeza: el esquema de la base de datos, los pasos de migración que lo cambian y los datos en producción. Confundirlas es la razón por la que los cambios parecen impredecibles.

Piensa en la regeneración como “reconstruir el código de la aplicación desde el modelo más reciente.” En una herramienta como AppMaster, esa reconstrucción puede ocurrir muchas veces durante el trabajo normal: ajustas un campo, modificas la lógica de negocio, agregas un endpoint, regeneras, pruebas, repites. La regeneración es frecuente. Tu base de datos de producción no debería serlo.

Aquí está el modelo simple.

  • Esquema: la estructura de tus tablas, columnas, índices y restricciones. Es lo que la base de datos espera.
  • Migraciones: los pasos ordenados y repetibles que mueven el esquema de una versión a la siguiente (y a veces transforman datos). Esto es lo que ejecutas en cada entorno.
  • Datos en runtime: los registros reales creados por usuarios y procesos. Deben permanecer válidos antes, durante y después del cambio.

El código regenerado debe tratarse como “la app actual que habla con el esquema actual.” Las migraciones son el puente que mantiene alineados el esquema y los datos en runtime mientras el código cambia.

Por qué la regeneración cambia las reglas

Si te regeneras con frecuencia, naturalmente harás muchas ediciones pequeñas al esquema. Eso es normal. El riesgo aparece cuando esas ediciones implican un cambio en la base de datos que no es compatible hacia atrás, o cuando tu migración no es determinista.

Una forma práctica de gestionar esto es planear la evolución de esquema segura ante regeneración como una serie de pasos pequeños y reversibles. En lugar de un gran interruptor, haces movimientos controlados que mantienen las rutas antiguas y nuevas de código funcionando juntas por un corto tiempo.

Por ejemplo, si quieres renombrar una columna usada por una API en producción, no la renombres inmediatamente. Primero añade la nueva columna, escribe en ambas, haz backfill de las filas existentes y luego cambia las lecturas a la nueva columna. Solo después de eso elimina la columna antigua. Cada paso es fácil de probar y, si algo falla, puedes pausar sin corromper datos.

Este modelo mental hace que las migraciones sean predecibles, incluso cuando la regeneración de código ocurre a diario.

Tipos de cambios de esquema y cuáles rompen producción

Cuando tu backend se regenera desde el esquema más reciente, el código suele asumir que la base de datos coincide con ese esquema ahora mismo. Por eso la evolución de esquema segura ante regeneración trata menos de “¿podemos cambiar la base de datos?” y más de “¿pueden los datos antiguos y las solicitudes antiguas sobrevivir mientras desplegamos el cambio?”

Algunos cambios son naturalmente seguros porque no invalidan filas o consultas existentes. Otros cambian el significado de los datos o eliminan algo que la app en ejecución aún espera, y ahí es donde ocurren incidentes en producción.

Bajo riesgo, usualmente seguro (aditivo)

Los cambios aditivos son los más fáciles de enviar porque pueden coexistir con datos antiguos.

  • Nueva tabla de la que nadie depende todavía.
  • Nueva columna nullable sin requerir un default.
  • Nuevo campo en la API que es opcional de extremo a extremo.

Ejemplo: añadir una columna nullable middle_name a la tabla users suele ser seguro. Las filas existentes siguen siendo válidas, el código regenerado puede leerla cuando está presente y las filas antiguas simplemente tienen NULL.

Riesgo medio (cambios de significado)

Estos cambios suelen “funcionar” técnicamente pero romper comportamiento. Necesitan coordinación porque la regeneración actualiza validaciones, modelos generados y suposiciones de la lógica de negocio.

Los renombres son la trampa clásica: renombrar phone a mobile_phone puede regenerar código que ya no lee phone, mientras que la producción sigue teniendo datos allí. Del mismo modo, cambiar unidades (almacenar precio en dólares vs en centavos) puede corromper cálculos si actualizas el código antes que los datos, o los datos antes que el código.

Los enums son otro filo. Endurecer un enum (eliminar valores) puede invalidar filas existentes. Ampliar un enum (añadir valores) suele ser seguro, pero solo si todos los caminos de código saben manejar el nuevo valor.

Un enfoque práctico es tratar los cambios de significado como “añadir nuevo, backfill, cambiar, luego eliminar.”

Alto riesgo (destructivo)

Los cambios destructivos son los que más a menudo rompen producción de inmediato, especialmente cuando la plataforma regenera código que deja de esperar la forma anterior.

Eliminar una columna, eliminar una tabla o cambiar una columna de nullable a not-null puede hacer que las escrituras fallen en cuanto una petición intente insertar una fila sin ese valor. Aunque pienses “todas las filas ya lo tienen”, el siguiente caso límite o un job en segundo plano puede demostrar lo contrario.

Si debes hacer un cambio a not-null, hazlo en fases: añade la columna como nullable, backfill, actualiza la lógica para que siempre la establezca y luego aplica not-null.

Cambios de rendimiento y seguridad (pueden bloquear escrituras)

Índices y restricciones no son “cambios de forma de datos”, pero aún pueden causar downtime. Crear un índice en una tabla grande o añadir una restricción UNIQUE puede bloquear escrituras el tiempo suficiente para provocar timeouts. En PostgreSQL, ciertas operaciones son más seguras cuando se hacen con métodos compatibles con operaciones online, pero el punto clave es el tiempo: realiza operaciones pesadas en periodos de baja carga y mide cuánto tardan en una copia de staging.

Cuando los cambios requieren cuidado extra en producción, planifica para:

  • Un despliegue en dos pasos (primero esquema, luego código, o viceversa) que sea compatible.
  • Backfills que se ejecuten por lotes.
  • Un camino claro de rollback (qué ocurre si el backend regenerado se activa antes de tiempo).
  • Consultas de verificación que prueben que los datos cumplen las nuevas reglas.
  • Un ticket de “eliminar campo antiguo después” para que la limpieza no ocurra en el mismo deploy.

Si usas una plataforma como AppMaster que regenera código del backend desde el Data Designer, la mentalidad más segura es: despliega cambios con los que los datos antiguos puedan convivir hoy; endurece las reglas solo después de que el sistema ya se haya adaptado.

Principios para cambios seguros ante regeneración

Los backends regenerados son geniales hasta que un cambio de esquema llega a producción y las filas antiguas no coinciden con la nueva forma. El objetivo de la evolución de esquema segura ante regeneración es simple: mantener tu app funcionando mientras la base de datos y el código regenerado se actualizan entre sí en pasos pequeños y predecibles.

Por defecto: “expandir, migrar, contraer”

Trata cada cambio significativo como tres movimientos. Primero, expande el esquema para que tanto el código antiguo como el nuevo puedan ejecutarse. Luego migra los datos. Solo después, contrae eliminando columnas antiguas, defaults o restricciones.

Una regla práctica: nunca combines “nueva estructura” y “limpieza destructiva” en el mismo deploy.

Soporta formas antiguas y nuevas por un tiempo

Asume que habrá un periodo donde:

  • algunas filas tienen los campos nuevos y otras no
  • algunas instancias de la app ejecutan código antiguo y otras código regenerado
  • jobs en background, importaciones o clientes móviles pueden ir retrasados

Diseña la base de datos para que ambas formas sean válidas durante ese solapamiento. Esto importa aún más cuando una plataforma regenera tu backend desde el modelo más reciente (por ejemplo, en AppMaster cuando actualizas el Data Designer y regeneras el backend en Go).

Haz compatibles las lecturas antes que las escrituras

Empieza por hacer que el código nuevo pueda leer datos antiguos de forma segura. Solo entonces cambia los caminos de escritura para producir la nueva forma de datos.

Por ejemplo, si divides un único campo status en status + status_reason, publica código que pueda manejar la ausencia de status_reason primero. Después de eso, empieza a escribir status_reason en las actualizaciones nuevas.

Decide qué hacer con datos parciales o desconocidos

Cuando añades enums, columnas non-null o restricciones más estrictas, decide de antemano qué hacer cuando faltan valores o aparecen valores inesperados:

  • permitir null temporalmente y luego backfill
  • establecer un valor por defecto seguro que no cambie el significado
  • mantener un valor “desconocido” para evitar fallar lecturas

Esto evita corrupción silenciosa (defaults equivocados) y fallos duros (nuevas restricciones rechazando filas antiguas).

Ten una historia de rollback para cada paso

El rollback es más fácil durante la fase de expansión. Si necesitas revertir, el código antiguo debería seguir funcionando contra el esquema expandido. Anota qué revertirías (solo código, o código más migración) y evita cambios destructivos hasta estar seguro de que no tendrás que deshacerlos.

Paso a paso: planear un cambio que sobreviva a la regeneración

Del esquema a una API funcional
Convierte tu modelo de datos en APIs y lógica de negocio que puedes ajustar según cambien los requisitos.
Crear app

Los backends regenerados no perdonan: si el esquema y el código generado no coinciden, producción suele encontrarlo primero. El enfoque más seguro es tratar cada cambio como un despliegue pequeño y reversible, incluso si construyes con herramientas sin código.

Comienza escribiendo la intención en lenguaje claro y cómo se ven tus datos hoy. Elige de 3 a 5 filas reales de producción (o un volcado reciente) y anota las partes problemáticas: valores vacíos, formatos antiguos, defaults sorprendentes. Esto evita diseñar un campo nuevo perfecto que los datos reales no puedan satisfacer.

Aquí hay una secuencia práctica que funciona bien cuando tu plataforma regenera el backend (por ejemplo, cuando AppMaster regenera servicios backend en Go desde el modelo del Data Designer):

  1. Expandir primero, no reemplazar. Añade columnas o tablas nuevas de forma aditiva. Haz los nuevos campos nullable al principio o dales defaults seguros. Si introduces una nueva relación, permite que la foreign key esté vacía hasta que la hayas poblado.

  2. Despliega el esquema expandido sin eliminar nada. Publica el cambio en la base de datos mientras el código antiguo sigue funcionando. El objetivo es: el código antiguo puede seguir escribiendo las columnas antiguas y la base de datos lo acepta.

  3. Backfill con un job controlado. Rellena los campos nuevos con un proceso por lotes que puedas monitorear y volver a ejecutar. Hazlo idempotente (ejecutarlo dos veces no debe corromper datos). Hazlo gradualmente si la tabla es grande y registra cuántas filas se actualizaron.

  4. Cambia lecturas primero, con fallback. Actualiza la lógica regenerada para preferir los campos nuevos, pero volver a los antiguos cuando falte la nueva información. Solo después de que las lecturas sean estables, cambia las escrituras a los campos nuevos.

  5. Limpia al final. Cuando tengas confianza (y un plan de rollback), elimina campos antiguos y endurece restricciones: aplica NOT NULL, añade UNIQUE y fuerza claves foráneas.

Ejemplo concreto: quieres reemplazar un status de texto libre por un status_id que apunte a una tabla statuses. Añade status_id como nullable, rellénalo desde los valores de texto existentes, actualiza la app para leer status_id pero usar status como fallback cuando sea null, y finalmente elimina status y haz status_id obligatorio. Esto mantiene cada regeneración segura porque la base de datos sigue siendo compatible en cada etapa.

Patrones prácticos reutilizables

Mantén compatibilidad durante actualizaciones
Añade campos opcionales primero para que clientes antiguos sigan funcionando durante las ventanas de despliegue.
Probar AppMaster

Cuando tu backend se regenera, pequeños ajustes en el esquema pueden afectar APIs, validaciones y formularios de UI. El objetivo de la evolución segura es hacer cambios de modo que los datos antiguos sigan siendo válidos mientras el código nuevo se despliega.

Patrón 1: Rename no disruptivo

Un renombrado directo es arriesgado porque registros antiguos y código antiguo aún esperan el campo original. Un enfoque más seguro es tratar el renombrado como un período corto de migración.

  • Añade la nueva columna (por ejemplo, customer_phone) y conserva la antigua (phone).
  • Actualiza la lógica para escribir en ambas columnas.
  • Backfill de filas existentes para que customer_phone esté lleno.
  • Cambia las lecturas a la nueva columna cuando la cobertura sea alta.
  • Elimina la columna antigua en una release posterior.

Esto funciona bien en herramientas como AppMaster donde la regeneración reconstruye modelos y endpoints desde el esquema actual. Dual-write mantiene felices a ambas generaciones de código durante la transición.

Patrón 2: Dividir un campo en dos

Dividir full_name en first_name y last_name es similar, pero el backfill es más complejo. Mantén full_name hasta estar seguro de que la división está completa.

Una regla práctica: no elimines el campo original hasta que cada registro esté backfilled o tenga un fallback claro. Si el parsing falla, guarda la cadena completa en last_name y marca el registro para revisión.

Patrón 3: Hacer un campo obligatorio

Convertir un campo nullable en obligatorio es un clásico que rompe producción. El orden seguro es: backfill primero, luego imponer la restricción.

El backfill puede ser mecánico (poner un default) o dirigido por negocio (pedir a usuarios que completen datos faltantes). Solo después de que los datos estén completos añade NOT NULL y actualiza validaciones. Si tu backend regenerado añade validaciones más estrictas automáticamente, esta secuencia evita fallos sorpresa.

Patrón 4: Cambiar un enum de forma segura

Los cambios de enum rompen cuando el código antiguo envía valores antiguos. Durante la transición, acepta ambos. Si reemplazas "pending" por "queued", mantén válidos ambos valores y mapea entre ellos en tu lógica. Cuando confirmes que ningún cliente envía el valor antiguo, elimínalo.

Si el cambio debe lanzarse en una sola release, reduce el ámbito del impacto:

  • Añade nuevos campos pero conserva los antiguos, aunque no se usen.
  • Usa un default en la base de datos para que las inserciones sigan funcionando.
  • Haz el código tolerante: lee del nuevo, cae al antiguo.
  • Añade una capa temporal de mapeo (valor antiguo entrante, valor nuevo almacenado).

Estos patrones mantienen las migraciones predecibles incluso cuando el código regenerado cambia rápidamente el comportamiento.

Errores comunes que causan sorpresas

Las mayores sorpresas ocurren cuando la gente trata la regeneración de código como un botón mágico de reset. Los backends regenerados pueden mantener tu código limpio, pero tu base de datos de producción sigue conteniendo la forma de ayer. La evolución de esquema segura ante regeneración significa planear para ambos: el código nuevo que se generará y los registros antiguos que aún están en las tablas.

Una trampa común es asumir que la plataforma “se encargará de las migraciones.” Por ejemplo, en AppMaster puedes regenerar un backend en Go desde tu modelo actualizado en el Data Designer, pero la plataforma no puede adivinar cómo quieres transformar datos reales de clientes. Si añades un campo obligatorio nuevo, todavía necesitas un plan claro para cómo las filas existentes obtendrán un valor.

Otra sorpresa es eliminar o renombrar campos demasiado pronto. Un campo puede parecer no usado en la UI principal, pero aún ser leído por un reporte, una exportación programada, un webhook o una pantalla de administración que alguien abre rara vez. El cambio parece seguro en pruebas y luego falla en producción porque un camino de código olvidado sigue esperando el nombre antiguo de la columna.

Aquí hay cinco errores que suelen provocar rollbacks nocturnos:

  • Cambiar el esquema y regenerar código, pero no escribir o verificar la migración de datos que hace válidas las filas antiguas.
  • Renombrar o borrar una columna antes de que todos los lectores y escritores hayan sido actualizados y desplegados.
  • Hacer backfill en una tabla grande sin comprobar cuánto tardará y si bloqueará otras escrituras.
  • Añadir una nueva restricción (NOT NULL, UNIQUE, clave foránea) primero y luego descubrir datos legacy que la rompen.
  • Olvidar jobs en background, exportaciones e informes que aún leen los campos antiguos.

Un escenario simple: renombras phone a mobile_number, añades una restricción NOT NULL y regeneras. Las pantallas de la app pueden funcionar, pero una exportación CSV antigua sigue seleccionando phone y miles de registros tienen mobile_number nulo. La solución suele ser un cambio por fases: añade la nueva columna, escribe en ambas durante un tiempo, backfill seguro, luego endurece restricciones y elimina la antigua solo después de tener pruebas de que nadie depende de ella.

Lista rápida pre-despliegue para migraciones más seguras

Visualiza tu esquema primero
Diseña tablas y relaciones en el Data Designer antes de tocar datos de producción.
Probarlo

Cuando tu backend se regenera, el código puede cambiar rápido, pero tus datos de producción no perdonarán sorpresas. Antes de enviar un cambio de esquema, ejecuta una breve comprobación de “¿puede esto fallar de forma segura?” Hace que la evolución segura ante regeneración sea aburrida (y eso es lo que quieres).

Las 5 comprobaciones que atrapan la mayoría de problemas

  • Tamaño y velocidad del backfill: estima cuántas filas existentes necesitan actualizarse (o reescribirse) y cuánto tardará en producción. Un backfill que está bien en una base pequeña puede tardar horas en datos reales y ralentizar la app.
  • Bloqueos y riesgo de downtime: identifica si el cambio puede bloquear escrituras. Algunas operaciones (alterar tablas grandes o cambiar tipos) pueden mantener locks el tiempo suficiente para causar timeouts. Si hay riesgo, planifica un despliegue más seguro (primero columna nueva, luego backfill, por último cambiar el código).
  • Compatibilidad entre código antiguo y nuevo esquema: asume que el backend antiguo puede ejecutarse un corto tiempo contra el esquema nuevo durante el deploy o un rollback. Pregunta: ¿la versión anterior seguirá leyendo y escribiendo sin colapsar? Si no, necesitas un release en dos pasos.
  • Defaults y comportamiento de nulls: para columnas nuevas, decide qué ocurre con las filas existentes. ¿Serán NULL o necesitan un default? Asegúrate de que tu lógica trate valores faltantes como normales, especialmente flags, campos de estado y timestamps.
  • Señales de monitorización a vigilar: elige las alarmas exactas que mirarás tras el deploy: tasa de errores (fallos en la API), consultas lentas en la base de datos, fallos en colas/jobs y cualquier acción clave del usuario (checkout, login, envío de formularios). También vigila errores silenciosos como pico en validaciones.

Un ejemplo rápido

Si añades un campo obligatorio nuevo como status a la tabla orders, no lo publiques como “NOT NULL, sin default” de golpe. Primero añádelo como nullable con un default para filas nuevas, despliega código regenerado que maneje la ausencia de status, luego backfill las filas antiguas y solo entonces endurece la restricción.

En AppMaster esta mentalidad es especialmente útil porque el backend puede regenerarse con frecuencia. Trata cada cambio de esquema como un pequeño release con rollback sencillo y tus migraciones seguirán siendo predecibles.

Ejemplo: evolucionar una app en vivo sin romper registros existentes

Elige tu camino de despliegue
Publica tu app regenerada en la nube o exporta el código fuente cuando necesites control total.
Desplegar app

Imagina una herramienta interna de soporte donde los agentes etiquetan tickets con un campo de texto libre llamado priority (ejemplos: "high", "urgent", "HIGH", "p1"). Quieres cambiar a un enum estricto para que reportes y reglas de enrutamiento no tengan que adivinar.

El enfoque seguro es un cambio en dos releases que mantenga las filas antiguas válidas mientras tu backend se regenera.

Release 1: expandir, escribir en ambas y backfill

Empieza expandiendo el esquema sin eliminar nada. Añade un nuevo campo enum, por ejemplo priority_enum con valores low, medium, high, urgent. Conserva el priority_text original.

Luego actualiza la lógica para que tickets nuevos y editados escriban en ambos campos. En una herramienta sin código como AppMaster, eso suele significar ajustar el modelo en el Data Designer y actualizar el Business Process para mapear la entrada al enum y también guardar el texto original.

A continuación, haz backfill de tickets existentes por lotes. Mapea textos comunes al enum (p1 y urgenturgent, HIGHhigh). Lo desconocido puede mapear temporalmente a medium mientras revisas.

Lo que ven los usuarios: idealmente nada cambia todavía. La UI puede seguir mostrando el mismo control de prioridad, pero tras bambalinas estás poblando el enum. Los reportes pueden empezar a usar el enum tan pronto como el backfill esté en marcha.

Release 2: contraer y eliminar la ruta antigua

Cuando tengas confianza, cambia las lecturas para usar solo priority_enum, actualiza filtros y dashboards y luego elimina priority_text en una migración posterior.

Antes de Release 2, valida con una muestra pequeña para atrapar casos límite:

  • Elige 20 a 50 tickets de diferentes equipos y antigüedad.
  • Compara la prioridad mostrada con el valor almacenado en el enum.
  • Revisa conteos por valor de enum para detectar picos sospechosos (por ejemplo, demasiados medium).

Si aparecen problemas, el rollback es sencillo porque Release 1 mantuvo el campo antiguo: redepliega la lógica de Release 1 y configura la UI para leer priority_text otra vez mientras arreglas el mapeo y vuelves a ejecutar el backfill.

Próximos pasos: hacer de la evolución de esquemas un hábito repetible

Si quieres migraciones predecibles, trata los cambios de esquema como un pequeño proyecto, no como una edición rápida. El objetivo es simple: cada cambio debe ser fácil de explicar, fácil de ensayar y difícil de romper por accidente.

Un modelo de datos visual ayuda porque hace el impacto visible antes del despliegue. Cuando puedes ver tablas, relaciones y tipos en un único lugar, notas cosas que son fáciles de pasar por alto en un script, como un campo obligatorio sin un default seguro o una relación que dejará huérfanos registros antiguos. Haz una pasada rápida de “quién depende de esto”: APIs, pantallas, reportes y jobs en background.

Cuando necesites cambiar un campo que ya está en uso, prefiere un periodo de transición corto con campos duplicados. Por ejemplo, añade phone_e164 mientras conservas phone_raw durante una o dos releases. Actualiza la lógica de negocio para leer del nuevo campo cuando exista y usar el antiguo como fallback. Escribe en ambos campos durante la transición y elimina el antiguo solo después de verificar que los datos están completamente backfilled.

La disciplina entre entornos convierte buenas intenciones en despliegues seguros. Mantén dev, staging y producción alineados, pero no los trates como idénticos.

  • Dev: prueba que el backend regenerado arranca y los flujos básicos funcionan tras la regeneración.
  • Staging: ejecuta el plan de migración completo sobre datos parecidos a producción y verifica consultas clave, reportes e importaciones.
  • Producción: despliega cuando tengas un plan de rollback, monitorización clara y un conjunto reducido de comprobaciones que deben pasar.

Haz de tu plan de migración un documento real, aunque sea corto. Incluye: qué cambia, el orden, cómo hacer backfill, cómo verificar y cómo revertir. Luego ejecútalo de extremo a extremo en un entorno de prueba antes de tocar producción.

Si usas AppMaster, apóyate en el Data Designer para razonar visualmente sobre el modelo y deja que la regeneración mantenga tu código consistente con el esquema actualizado. El hábito que mantiene todo predecible es hacer las migraciones explícitas: puedes iterar rápido, pero cada cambio tiene un camino planeado para los datos de producción existentes.

Fácil de empezar
Crea algo sorprendente

Experimente con AppMaster con plan gratuito.
Cuando esté listo, puede elegir la suscripción adecuada.

Empieza