Skip to content

How to migrate

RBoelter edited this page Mar 22, 2022 · 11 revisions

Disclaimer

This entry was written with a different development process in mind. Currently, you see a faster, easier workflow that omits migrations in development. Additionally, there is no way to migrate in the test environment and therefore no migrations needed for this environment. So if you don't plan to migrate within the development process, this advice is outdated by now.

What is a migration in Symfony?

Simply put, a database change required to align your entities with your schema. Migrations are an important piece in our tool belt to synchronize database and application. Symfony can generate basic migrations automatically and this saves huge amounts of time. If you are not familiar with what a migration looks like, please learn more about it before you continue reading.

Why do we need a wiki page for that?

Unfortunately automatically generated migrations will not prevent data loss. So when you change an entity in your model and move the attribute to another entity, Symfony will generate a alter table 1 drop column_a and then alter table 2 add column_a for those two entities. This behaviour is fine for development and for testing. In those two environments our data should be ephemeral and we prevent errors that way. In production whoever our data should never be deleted.

Tradeoffs we encounter

This leads to two possible decisions. We accept the Symfony defaults and have just one (arbitrary) migration directory with all migrations or we create a explizit migration directories for all environments mentioned above. What we gain in each case is essential to understand the current design of how we handle migrations.

Symfony defaults

If we have just one migration directory, our solution is simple and easy to understand. This is evident in every symfonycast tutorial provided by the developer curriculum. Yet, rarely does any of those tutorials show examples of an complete application lifecycle. As soon as the application enters production no simple migration is possible. But no developer will solve issues and adds new features without changing the database. This leaves two options for the developer.

  1. Make any migration prevent dataloss and garantee compliance towards production at all time. This will cost more time.
  2. Change the commited migrations before every release and rewrite history frequently. This implies no CI process ever.

Both options will decrease the productivity and none of them adds value to the codebase. Using the Symfony defaults means for the developer an easy development and a time consuming production time.

Migration directory for every environment

This solution is more involved and requires some explanation of the whole process. We assume for the sake of this paragraph, that we only have two environments - dev and prod. While in dev data is not important. We can delete and rewrite to our liking, and it should have no consequences. If we take this experimentation mindset a step further, we don't even need the same database for dev. It would be sufficed to create a new database everytime and Symfony provides tools to fill this new database with samples. With this assumption set, we can safely ignore all dev migrations. The database for development is completely ephemeral and can be reproduced with ideally one command.

Now our production setup. We encounter the complete opposite. Every migration counts, and they must be in version control. But we need way less migrations in prod, than we would have needed in dev. Symfony allows us to diff the database with the current entity mapping information. This means, if a developer needs 10 migrations in dev to end up with a working feature, we need to generate just one production migration to apply the schema changes. Additionally, we also only need to make sure no data is deleted one time. Our repository will grow slower, changes are more meaningful and nothing is done twice. Just to highlight the value of this option, such a process could not be done with Symfony's defaults.

Using a migration directory for every environment grants us flexibility, saves time and allows us to just add meaningful changes in our repository. Only how to configure such a process for Symfony can be a challenge.

The holy grail of database changes

The arguments made for both options don't hide any intention. We handle migrations in the second way explicitly to prevent the problems of Symfony's defaults. Yet, this shouldn't be without doubt. If you can find a simpler solution to the problem, feel free to contribute and change the codebase. What you found here, is the best we came up with.

Tech Stack

Have a look at the docs or some thought provoking articles to get started.

Clone this wiki locally