There comes a time in every developer’s life when they need to do a database migration. Because business requirements change frequently, database schemas need to be updated from time to time. When you think of making changes to your code, it’s easy to roll back with git or feature flags, but why can’t the same principle be applied to database migrations?
What is a Database Migration?
In this post, we are talking about database migrations in the context of updating schemas rather than going from one platform to another. If you’re interested in platform migration, check out our Managing a Monolith Breakup post.
A lot of companies choose to undertake a database migration to update their schemas for a variety of reasons, including changes in the requirements of their data, to take advantage of cost reductions offered by cloud-based platforms, or simply data reorganization.
The Biggest Risk of Database Migration
The biggest risk when it comes to a database migration is, quite obviously, the loss of data. Understandably, for nearly every organization, this is an unacceptable risk. To mitigate that risk, development teams need a way to test that the data remains intact throughout the migration.
Use Feature Flags to Migrate Your Schemas
A common misconception about feature flags is that they can only be used for front end feature releases. However, feature flags can play a crucial role in your architectural strategy as well.
Let’s take an example of adding a middle name to an existing schema. Currently, your UI just asks for first name and last name, and we want to add a middle name column to the schema. The first thing you need to do is add a new column in the database. This is an additive change that is backward compatible. If no one is using that code, it’s just sitting there. When you actually make the code changes to use that middle name, you should put them behind a feature flag. The schema will work whether the flag is on or off, and if you turn the flag off it won’t break anything. If, in the future, you decide that you do not want to record people’s middle names anymore, you could perform a DB migration that removes that column. However, that is not backward compatible because, in the future, your code will look for a column that is not there anymore.
The safe and recommended way to do this is to wrap your feature flag around the elements of your codebase, not your database. If there is a problem with your code and you need to revert, or if you decide you do not want to ask for the users’ middle names anymore, all you would need to do is change the code that is behind the feature flag, without touching the database code. Then, once the feature flag is deactivated, you could do a separate migration that will just drop that column.
Preserve Backwards Compatibility in Database Migrations with Feature Flags
Let’s say you are in front of a frozen lake, and you are not sure if it is stable enough to hold you while you walk on it. You stretch out your right leg, gently apply pressure, and then slowly move your left leg to meet your right leg. You do this continuously to build your confidence until you reach the other end of the lake. If however, you feel the ice crack underneath your leg, you would slowly revert your actions and go back. This idea is called the expand-contract pattern.
Just as you need different versions of your software to work at the same time, you also need different versions of the database to work at the same time. In reality, you cant stop the world, update your code, and then start the world again. You need to do it gradually, which means more than one version will have to work at a time with the database. When you are migrating to a new database schema, you expand the schema to work with the old version and the new version and then contract to work only with the new. This allows the gradual rollout of the new changes to be successful while knowing that the old code still works for your users who haven’t gotten it yet. For this process to be effective, each change on its own should be backward compatible, so that just in case you need to roll back, your database will still be valid.
Feature flags give you the benefit of a layer of risk mitigation. For example, if you update your database and then immediately upgrade to version 2 of your code and there’s a bug, what do you do? Enter feature flags. The database still has to work after you release the feature because the change will not happen to everyone instantaneously - it will happen incrementally. By having a backward compatible migration, the risk is drastically reduced.
Learn More About Database Migrations and Feature Flags
Database migrations can cause developers problems if not done correctly. Lucky for you, we’ve got you covered! If you’re interested in learning more
- Read more about feature flags and incremental, backward-compatible database changes in chapter 6 of our free Feature Flag Best Practices eBook
- Learn more about reducing the risk of database migrations with feature flags
- Watch this video on Feature Flag Best Practices
- Stay up to date on controlled rollouts