All developers will at some time or other have to deploy code that changes the structure of a database. You might have downtime during these deploys due to database changes being required by the new code that you just deployed. There are easy ways to work around those downtimes and provide you a real zero downtime deployment process.
How does that work? I found out that to explain the basics of how to handle database migrations properly, it works better with some examples.
Before jumping to the examples, let me tell you that we, at Rainforest, are using Rails and its built-in database migration system, so this might be slightly different for you but the idea is the same. We also use Postgres which doesn't create the obstacles that some other database systems have, for example with locking tables on schema changes. If you use MySQL, you should definitely take a look at the Large Hadron Migrator which is used by a bunch of people including GitHub and Shopify.
Before we get started, if you remember one thing from this blog post it should be plan your database migrations carefully. It takes more time to do migrations with no downtime but it is worth it.
This is an easy one.
Before, you would have added a new column, let's call it 'status' and deployed the code at the same time. For a brief moment, your could have tried to insert data in a column that is not existing (yet) and experience errors which could make your application unusable. Let's see how we can do this safely without impacting our clients.
As you can see, we did not add code to use it in the first place but just added the new column, and then in a second phase we actually started to use it. There was no downtime and no client was harmed in the making of this example.
This is already way more complex.
Let's say you have a column for which you want to change the type. There could be a couple of reasons for that, but let's say you have a "text" column you are using to store serialized JSON. Hey, this could be a native Postgres JSON column, right? Let's do the change.
We'll have to go through a few phases here.
ruby class MyModel serialize :my_column before_save do my_column_JSON = my_column end end
We're done, you can move on to your next feature!
You probably got the point now, right? So let's make this one more straightforward.
"Hey JP, there is no downtime usually when I do this!". Correct. I just wanted to tell you a little trick we use at Rainforest. Don't you like free tips?
If you just remove the column, well, this is not reversible and you can't rollback as the data will have been deleted.
The idea is simple: don't delete it just yet. Just rename the column to "mycolumnnamedeprecated27062014" and boom, you can rollback!
I hope that will help you to get your deployment process as frictionless as possible.
Thanks for reading.
Want to deploy code faster without losing quality? Here's how 5 companies have scaled QA practices to reduce downtime and keep up with faster deployment cycles.