# Migraciones de base de datos desde cero

**Categoría:** Bases de datos · **Nivel:** Intermedio · **Lectura:** 21 min
**Publicada:** 2026-07-28 · **Actualizada:** 2026-07-28 · **Autoría:** Underc0de
**Versión HTML (canónica):** https://underc0de.org/guias/bases-de-datos/migraciones-de-base-de-datos-desde-cero/

## Respuesta rápida

Las **migraciones de base de datos** son la forma de **versionar y gestionar los cambios del esquema** —las tablas, columnas, índices y relaciones— igual que se versiona el código con Git. El problema que resuelven es real y común: el código se versiona con disciplina, pero el **esquema de la base de datos**, demasiadas veces, se cambia **a mano y sin registro** —alguien añade una columna directamente en producción, otro la modifica en su entorno local, y nadie sabe con certeza en qué estado está cada base—. Eso lleva al **caos**: entornos que no coinciden, cambios que se pierden, despliegues que fallan porque el esquema no es el esperado. Una migración es un **paso de cambio del esquema, versionado y ordenado**: un archivo (con SQL o con instrucciones) que describe *una* modificación —«crear la tabla pedidos», «añadir la columna teléfono a clientes»—, con un número o marca de tiempo que fija su **orden**. Las migraciones tienen dos propiedades clave. Son **incrementales**: cada una es un paso pequeño que se aplica *sobre* el estado anterior, y la secuencia completa de migraciones lleva cualquier base desde vacía hasta el estado actual, en orden. Y muchas son **reversibles**: además del cambio «hacia adelante» (aplicar), definen cómo **deshacerlo** (revertir), lo que permite volver atrás si algo sale mal. Una herramienta de migraciones lleva la **cuenta de qué migraciones ya se aplicaron** en cada base, así que aplicar las pendientes lleva cualquier entorno al estado correcto de forma automática y reproducible. ¿Por qué son **imprescindibles en equipo**? Porque cuando varias personas cambian el esquema, las migraciones son la **única forma de que todos los entornos evolucionen igual**: las migraciones viven *junto al código* en el control de versiones, así que quien descarga el código descarga también los cambios del esquema, y los aplica en orden para tener exactamente la misma base. Sin migraciones, cada base es un misterio; con ellas, el esquema es **reproducible, auditable y coordinado**. Buenas prácticas: cada migración es **pequeña y hace una cosa**, **nunca se edita una migración ya aplicada** (se crea una nueva que corrige), y **backup antes de migrar producción**. Es traer al esquema la misma disciplina que ya tiene el código.

## El esquema sin control

Hay una asimetría curiosa en cómo se trata el código y la base de datos. El **código** se versiona con esmero: cada cambio queda registrado en Git, con su autor, su fecha y su motivo, y todos trabajan sobre la misma historia. Pero el **esquema de la base de datos** —la estructura de tablas y columnas— demasiadas veces se cambia **a mano**: alguien ejecuta un `ALTER TABLE` directamente en un entorno, sin dejar registro. El resultado es que, mientras el código está bajo control, el esquema es un **territorio sin ley**: nadie sabe con certeza qué cambios se hicieron, cuándo, ni si todos los entornos (el de cada desarrollador, el de pruebas, el de producción) tienen la *misma* estructura.

> **El caos de los entornos que no coinciden**
>
> La consecuencia de un esquema sin control es el **caos de la desincronización**. Un desarrollador añade una columna en *su* base local para una función nueva, pero se olvida de comunicarlo; otro despliega su código en producción y **falla**, porque esa columna no existe ahí. Alguien arregla un problema modificando una tabla directamente en producción, pero ese cambio **no está en ningún sitio**, así que la próxima vez que se recrea el entorno, desaparece. Con el tiempo, el entorno de desarrollo, el de pruebas y el de producción **divergen**, y nadie sabe cuál es el estado «correcto» del esquema. Esto provoca despliegues que fallan, bugs que solo aparecen en un entorno, y una enorme pérdida de tiempo intentando averiguar «¿por qué en mi máquina funciona y en producción no?». La raíz es siempre la misma: **el esquema no está versionado**, así que no hay una única fuente de verdad sobre cuál debe ser su estado. Las migraciones existen precisamente para eliminar este caos.

## Qué son las migraciones

Una **migración** es un cambio del esquema convertido en un **paso versionado**. Sus dos propiedades definitorias:

| Propiedad | Qué significa |
|---|---|
| Incremental y ordenada | Cada migración es un paso sobre el estado anterior; la secuencia lleva de vacía al estado actual |
| Reversible (a menudo) | Define cómo aplicar el cambio y cómo deshacerlo, para poder volver atrás |

> **Atención**
>
> Las dos propiedades de las migraciones son lo que las hace tan potentes. Que sean **incrementales** significa que cada migración es un **paso pequeño** —«crear esta tabla», «añadir esta columna», «crear este índice»— que se aplica *sobre* el estado dejado por las anteriores. La **secuencia completa** de migraciones, aplicada en orden desde la primera, reconstruye el esquema entero **desde cero**: una base vacía + todas las migraciones = el esquema actual, exactamente. Esto convierte el esquema en algo **reproducible**: cualquiera puede recrear la estructura correcta aplicando las migraciones en orden. Que muchas sean **reversibles** significa que, además del cambio «hacia adelante» (cómo *aplicar* la migración), definen el cambio «hacia atrás» (cómo *deshacerla*): si una migración crea una tabla, su reverso la elimina. Esto permite **volver a un estado anterior** si una migración causa problemas. La pieza que hace funcionar todo es la **herramienta de migraciones**, que lleva un **registro de qué migraciones ya se aplicaron** en cada base de datos concreta. Así, cuando ejecutás «migrar», la herramienta mira qué falta por aplicar y ejecuta *solo las pendientes, en orden*, dejando esa base exactamente en el estado esperado. No importa si la base estaba varias versiones atrás: la herramienta la pone al día automáticamente.

## Equipo y buenas prácticas

Donde las migraciones pasan de «útiles» a **imprescindibles** es en el trabajo en **equipo**. Y su uso correcto sigue unas pocas reglas:

- **Las migraciones viven con el código.** Se guardan en el control de versiones junto al código, así que quien descarga el proyecto descarga también los cambios del esquema.
- **Cada migración pequeña y con un propósito.** Un cambio por migración es más fácil de entender, revisar y, si hace falta, revertir.
- **Nunca editar una migración ya aplicada.** Si algo está mal, se crea una migración *nueva* que lo corrige; editar una vieja rompe la sincronía.
- **Backup antes de migrar producción.** Una migración modifica la estructura; ante un fallo, la copia es la red de seguridad.
- **Probar la migración antes de producción.** Aplicarla primero en un entorno de pruebas para detectar problemas.

> **Atención**
>
> Cuando **una sola persona** trabaja en un proyecto, quizá pueda apañarse cambiando el esquema a mano (aunque no debería). Pero en cuanto hay **un equipo**, las migraciones dejan de ser opcionales. El motivo: si varias personas cambian el esquema y esos cambios no están versionados *junto al código*, es imposible que todos los entornos evolucionen igual —cada desarrollador tendría su base ligeramente distinta, y producción, otra más—. Con migraciones, en cambio, los cambios del esquema **viajan con el código** en el control de versiones: cuando un compañero descarga (con `git pull`) el trabajo del resto, descarga también las **nuevas migraciones**, y al aplicarlas su base local queda **idéntica** a la de los demás. Y al desplegar, se aplican las migraciones pendientes y producción queda al día automáticamente. Así, el esquema pasa de ser un misterio que cada uno gestiona por su cuenta a ser algo **reproducible, auditable y coordinado**, con una única fuente de verdad. La regla más importante para que esto funcione es **nunca editar una migración ya aplicada**: como los demás ya la ejecutaron, cambiarla haría que su base y la tuya divergieran silenciosamente; si hay que corregir algo, se añade una *nueva* migración. Es la misma filosofía del control de versiones del código —la historia no se reescribe, se avanza—, aplicada al esquema. Combinado con [respaldos](../respaldos-y-restauracion-de-bases-de-datos/index.md) antes de tocar producción, es la forma profesional de hacer evolucionar una base de datos.

## Errores frecuentes

- **Cambiar el esquema a mano en producción.** El cambio no queda registrado y los entornos divergen; usar migraciones.
- **Editar una migración ya aplicada.** Rompe la sincronía con quienes ya la ejecutaron; crear una nueva que corrija.
- **Migraciones enormes que hacen muchas cosas.** Difíciles de entender y revertir; una migración, un cambio.
- **No guardar las migraciones con el código.** Pierden su valor si no viajan con el proyecto en el control de versiones.
- **Migrar producción sin backup ni prueba previa.** Un fallo sin red de seguridad puede ser irreversible.
- **No definir el reverso de las migraciones.** Sin la parte reversible, volver atrás ante un problema es mucho más difícil.
- **Aplicar migraciones fuera de orden.** El orden importa; cada una asume el estado dejado por las anteriores.

## Preguntas frecuentes

**¿Qué son las migraciones de base de datos?**
Las migraciones de base de datos son la forma de versionar y gestionar los cambios en el esquema de una base de datos, es decir, en su estructura de tablas, columnas, índices y relaciones, aplicando a esos cambios la misma disciplina de control de versiones que se aplica al código fuente. Cada migración es un paso de cambio del esquema, versionado y ordenado, que consiste en un archivo, con instrucciones en SQL o en otro formato, que describe una modificación concreta del esquema, como crear una tabla, añadir una columna a una tabla existente, crear un índice o modificar una relación, y que lleva asociado un número o una marca de tiempo que fija su orden respecto a las demás migraciones. Las migraciones tienen dos propiedades fundamentales. La primera es que son incrementales y ordenadas, lo que significa que cada migración es un paso pequeño que se aplica sobre el estado dejado por las migraciones anteriores, de modo que la secuencia completa de migraciones, aplicada en orden desde la primera, reconstruye el esquema entero desde cero, ya que una base de datos vacía más todas las migraciones aplicadas en orden da como resultado exactamente el esquema actual. La segunda propiedad es que muchas migraciones son reversibles, lo que significa que, además de definir el cambio hacia adelante, es decir, cómo aplicar la migración, definen también el cambio hacia atrás, es decir, cómo deshacerla, de manera que si una migración crea una tabla su reverso la elimina, lo que permite volver a un estado anterior si algo sale mal. El funcionamiento de las migraciones se apoya en una herramienta de migraciones que lleva un registro de qué migraciones ya se han aplicado en cada base de datos concreta, de modo que cuando se ejecuta la orden de migrar, la herramienta comprueba qué migraciones faltan por aplicar y ejecuta solo las pendientes en orden, dejando esa base de datos exactamente en el estado esperado, con independencia de en qué punto estuviera antes. Las migraciones resuelven el problema del caos que se produce cuando el esquema de la base de datos se cambia a mano y sin registro, y son especialmente imprescindibles en el trabajo en equipo, ya que al vivir junto al código en el control de versiones garantizan que todos los entornos evolucionen de la misma manera, convirtiendo el esquema en algo reproducible, auditable y coordinado.

**¿Qué problema resuelven las migraciones?**
Las migraciones resuelven el problema del caos que se produce cuando el esquema de una base de datos se cambia a mano y sin registro, lo que lleva a que los distintos entornos dejen de coincidir, a que los cambios se pierdan y a que los despliegues fallen porque el esquema no está en el estado esperado. El origen del problema está en una asimetría curiosa en cómo se suelen tratar el código y la base de datos. El código fuente se versiona con esmero mediante un sistema de control de versiones, de modo que cada cambio queda registrado con su autor, su fecha y su motivo, y todo el equipo trabaja sobre la misma historia compartida. Sin embargo, el esquema de la base de datos, es decir, su estructura de tablas y columnas, demasiadas veces se cambia a mano, ejecutando modificaciones directamente en un entorno sin dejar ningún registro de lo que se hizo. El resultado es que, mientras el código está bajo control, el esquema queda como un territorio sin ley, en el que nadie sabe con certeza qué cambios se hicieron, cuándo se hicieron ni si todos los entornos tienen la misma estructura. La consecuencia de este esquema sin control es el caos de la desincronización entre entornos. Por ejemplo, un desarrollador añade una columna en su base de datos local para una nueva función, pero se olvida de comunicarlo, y cuando otro compañero despliega su código en producción, este falla porque esa columna no existe allí. O bien alguien arregla un problema modificando una tabla directamente en producción, pero ese cambio no queda registrado en ningún sitio, de modo que la próxima vez que se recrea el entorno, el cambio desaparece. Con el tiempo, el entorno de desarrollo de cada persona, el de pruebas y el de producción divergen, y nadie sabe cuál es el estado correcto del esquema, lo que provoca despliegues fallidos, errores que solo aparecen en algunos entornos y una gran pérdida de tiempo intentando averiguar por qué algo funciona en una máquina y no en otra. La raíz de todos estos problemas es siempre la misma, que es que el esquema no está versionado y, por tanto, no existe una única fuente de verdad sobre cuál debe ser su estado. Las migraciones resuelven este problema aportando esa fuente de verdad, ya que convierten cada cambio del esquema en un paso versionado y ordenado que vive junto al código, de modo que cualquier entorno puede llevarse al estado correcto de forma automática y reproducible aplicando las migraciones pendientes.

**¿Qué significa que las migraciones son incrementales y reversibles?**
Que las migraciones sean incrementales significa que cada una es un paso pequeño que se aplica sobre el estado dejado por las anteriores, de modo que la secuencia completa reconstruye el esquema desde cero, y que sean reversibles significa que, además de definir cómo aplicar el cambio, definen cómo deshacerlo para poder volver atrás. Estas dos propiedades son lo que hace tan potentes a las migraciones. La propiedad de ser incrementales se refiere a que cada migración representa un paso pequeño y concreto en la evolución del esquema, como crear una tabla determinada, añadir una columna o crear un índice, y que ese paso se aplica sobre el estado del esquema que dejaron las migraciones anteriores. Esto implica que las migraciones forman una secuencia ordenada en la que cada una construye sobre la previa, de manera que si se parte de una base de datos vacía y se aplican todas las migraciones en orden, desde la primera hasta la última, se reconstruye el esquema completo y actual exactamente como debe ser. Esta característica convierte el esquema en algo reproducible, ya que cualquier persona puede recrear la estructura correcta de la base de datos simplemente aplicando la secuencia de migraciones en orden, sin necesidad de conocer manualmente todos los cambios que se han ido haciendo. La propiedad de ser reversibles se refiere a que muchas migraciones, además de definir el cambio hacia adelante, es decir, la operación que aplica la modificación, definen también el cambio hacia atrás, es decir, la operación que la deshace. Por ejemplo, si una migración crea una tabla, su parte reversible define cómo eliminar esa tabla, y si añade una columna, su reverso define cómo quitarla. Esta reversibilidad permite volver a un estado anterior del esquema si una migración causa problemas, deshaciendo los cambios de forma controlada. La pieza que hace funcionar todo este mecanismo es la herramienta de migraciones, que lleva un registro de qué migraciones ya se han aplicado en cada base de datos concreta. Gracias a ese registro, cuando se ejecuta la orden de migrar, la herramienta comprueba qué migraciones están pendientes de aplicar en esa base y ejecuta únicamente esas, en el orden correcto, dejando la base de datos exactamente en el estado esperado. Esto significa que no importa en qué punto de la secuencia estuviera la base de datos, ya que la herramienta la pone al día automáticamente aplicando solo lo que falta, lo que hace que el proceso sea automático, reproducible y fiable en cualquier entorno.

**¿Por qué las migraciones son imprescindibles en equipo?**
Las migraciones son imprescindibles en el trabajo en equipo porque son la única forma de garantizar que todos los entornos evolucionen de la misma manera cuando varias personas cambian el esquema de la base de datos, ya que al vivir junto al código en el control de versiones, los cambios del esquema viajan con el código y se aplican de forma coordinada y ordenada en cada entorno. Cuando una sola persona trabaja en un proyecto, quizá pueda arreglárselas cambiando el esquema a mano, aunque no sea lo recomendable, ya que solo tiene que coordinarse consigo misma. Pero en cuanto hay un equipo de varias personas, la situación cambia por completo y las migraciones dejan de ser opcionales. El motivo es que si varias personas cambian el esquema de la base de datos y esos cambios no están versionados junto al código, resulta imposible que todos los entornos evolucionen igual, ya que cada desarrollador tendría su base de datos local ligeramente distinta, según los cambios que hubiera hecho o dejado de hacer, y el entorno de producción tendría otra estructura diferente, sin que nadie supiera cuál es la correcta. Con las migraciones, en cambio, los cambios del esquema viajan junto al código en el sistema de control de versiones, formando parte del mismo repositorio. Esto significa que cuando un miembro del equipo descarga el trabajo del resto, obteniendo las últimas versiones del código, descarga también las nuevas migraciones que otros hayan creado, y al aplicarlas en su entorno, su base de datos local queda idéntica a la de los demás. Del mismo modo, cuando se despliega la aplicación en producción, se aplican las migraciones pendientes y la base de datos de producción queda automáticamente al día con el estado correcto del esquema. De este modo, el esquema deja de ser un misterio que cada persona gestiona por su cuenta y se convierte en algo reproducible, auditable y coordinado, con una única fuente de verdad compartida por todo el equipo. Para que este sistema funcione correctamente, la regla más importante es no editar nunca una migración que ya ha sido aplicada, ya que como los demás miembros del equipo ya la han ejecutado en sus entornos, modificarla haría que su base de datos y la de quien la modifica divergieran de forma silenciosa; si hay que corregir algo, se debe crear una migración nueva que aplique la corrección. Esta filosofía es la misma que la del control de versiones del código, en la que la historia no se reescribe sino que se avanza añadiendo nuevos cambios, aplicada ahora a la evolución del esquema de la base de datos, lo que permite un desarrollo en equipo ordenado y sin los conflictos y sorpresas del esquema sin control.

**¿Por qué no debo editar una migración ya aplicada?**
No se debe editar una migración que ya ha sido aplicada porque hacerlo rompe la sincronía entre las distintas bases de datos, ya que los demás miembros del equipo y los entornos que ya ejecutaron esa migración tienen el esquema en el estado que dejó la versión original, y modificarla haría que su base de datos y la de quien la edita divergieran de forma silenciosa e incontrolada. Para entender por qué esto es un problema hay que recordar cómo funcionan las migraciones. Una herramienta de migraciones lleva un registro de qué migraciones se han aplicado ya en cada base de datos, de modo que cada migración se aplica una sola vez, cuando está pendiente, y a partir de entonces se considera parte del historial ya ejecutado de esa base. Cuando una migración ya se ha aplicado en varios entornos, por ejemplo en las bases de datos locales de varios desarrolladores y en producción, todos esos entornos tienen el esquema en el estado que produjo esa migración tal como estaba escrita en el momento de aplicarla. Si alguien edita esa migración después, cambiando lo que hace, se produce una inconsistencia, porque los entornos que ya la aplicaron con la versión anterior no volverán a aplicarla, al estar ya registrada como ejecutada, y por tanto no recibirán el cambio de la edición, mientras que un entorno nuevo que aplique la migración por primera vez lo hará con la versión editada, quedando en un estado distinto. El resultado es que unas bases de datos tendrán el esquema según la versión original de la migración y otras según la versión editada, divergiendo de forma silenciosa, sin que la herramienta lo detecte, ya que para ella la migración simplemente está aplicada. Esta divergencia oculta es precisamente el tipo de caos que las migraciones pretenden evitar, y por eso editar una migración ya aplicada es una mala práctica que hay que evitar. La forma correcta de corregir o modificar algo cuando una migración ya se ha aplicado es crear una migración nueva que realice la corrección o el cambio deseado, la cual se aplicará como un paso adicional en todos los entornos, manteniendo la sincronía. Esta regla es equivalente a la filosofía del control de versiones del código, en la que no se reescribe la historia ya compartida, sino que se avanza añadiendo nuevos cambios encima. Del mismo modo que en el código no se modifican los cambios ya publicados y compartidos con el equipo sino que se hacen nuevos, en las migraciones no se editan las ya aplicadas sino que se crean nuevas, garantizando así que todos los entornos evolucionen de forma coordinada y sin divergencias silenciosas.

**¿Qué buenas prácticas debo seguir con las migraciones?**
Las buenas prácticas fundamentales al trabajar con migraciones de base de datos incluyen guardarlas junto al código en el control de versiones, hacer cada migración pequeña y con un único propósito, no editar nunca una migración ya aplicada, hacer una copia de seguridad antes de migrar producción y probar las migraciones antes de aplicarlas en el entorno de producción. La primera buena práctica es guardar las migraciones junto al código en el sistema de control de versiones, ya que esto es lo que hace que los cambios del esquema viajen con el código, de modo que quien descarga el proyecto obtiene también los cambios del esquema y puede aplicarlos para tener la misma base de datos que el resto del equipo, garantizando la coordinación y la reproducibilidad. La segunda es hacer que cada migración sea pequeña y tenga un único propósito, es decir, que realice un solo cambio o un conjunto reducido y coherente de cambios, ya que una migración pequeña es más fácil de entender, de revisar y, si fuera necesario, de revertir, mientras que las migraciones enormes que hacen muchas cosas a la vez son difíciles de comprender y de deshacer. La tercera, y una de las más importantes, es no editar nunca una migración que ya ha sido aplicada, ya que hacerlo rompería la sincronía con los entornos y las personas que ya la ejecutaron, provocando divergencias silenciosas; si hay que corregir algo, se debe crear una migración nueva que aplique la corrección. La cuarta es hacer una copia de seguridad de la base de datos antes de aplicar una migración en el entorno de producción, ya que una migración modifica la estructura de la base de datos y, ante un posible fallo, la copia de seguridad es la red de seguridad que permite recuperar el estado anterior. La quinta es probar las migraciones antes de aplicarlas en producción, ejecutándolas primero en un entorno de pruebas que replique las condiciones de producción, para detectar posibles problemas de forma controlada antes de tocar el entorno real. Además de estas prácticas, es muy recomendable definir la parte reversible de las migraciones siempre que sea posible, es decir, especificar cómo deshacer cada cambio, ya que esto facilita enormemente volver atrás si una migración causa problemas. También es importante aplicar las migraciones en orden, respetando la secuencia, ya que cada migración asume el estado dejado por las anteriores. Siguiendo estas buenas prácticas, las migraciones cumplen plenamente su función de aportar orden, reproducibilidad y coordinación a la evolución del esquema de la base de datos, evitando el caos que se produce cuando el esquema se cambia a mano y sin control, y permitiendo un desarrollo profesional y en equipo de la base de datos.

## Fuentes

Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 28 de julio de 2026.

### Aportes de la comunidad Underc0de

1. **Underc0de, foro.** [Bases de datos](https://underc0de.org/foro/bases-de-datos/). Gestión de esquemas.
2. **Underc0de, foro.** [Programación general](https://underc0de.org/foro/programacion-general/). Desarrollo en equipo.

### Documentación oficial

1. **Flyway.** [Flyway](https://flywaydb.org/). Herramienta de migraciones de base de datos.
2. **Liquibase.** [Liquibase](https://www.liquibase.org/). Gestión de cambios de esquema.
3. **The Twelve-Factor App.** [The Twelve-Factor App](https://12factor.net/). Buenas prácticas de despliegue.
4. **PostgreSQL.** [Data Definition](https://www.postgresql.org/docs/current/ddl.html). Modificación del esquema.

## Guías relacionadas

- [Diseñar una base de datos](../como-disenar-una-base-de-datos-sencilla/index.md)
- [Normalización](../normalizacion-de-bases-de-datos/index.md)
- [Respaldos y restauración](../respaldos-y-restauracion-de-bases-de-datos/index.md)
- [Migrar WordPress](../../desarrollo-web/como-migrar-wordpress-a-otro-hosting-o-dominio/index.md)
- [Índice de Bases de datos](../index.md)
