Interested in taking your Rails migration code to the next level? Welcome. You’re in the right place.
What’s that? Somebody in the back says they’re not already up on the basics? No problem. The Rails Guide on migrations is like most Rails guides — pretty darn awesome. It’ll have you adding tables, dropping columns and altering multi-column indices before you know it.
For the rest of you who know the basics, let’s learn what awesome Rails programmers already know about migrations.
Migrations can bring down a busy site in a hurry. Many things you do in a migration will lock the table you’re touching, which will block every SQL query and every Rails route that touches that table, sometimes for minutes or hours. You can’t “scale” your way out of it — you only get one database, and it’s locked for all app servers.
A question you’ll occasionally see: when do you run your migrations in production? There’s a standard answer, so let’s talk about it.
You’ll run your migrations before you deploy new code. In general, that means “every time you push code to production, you run all the migrations since the last time you pushed code to production. Do it before you replace the old code.”
Easy enough. Why?
First, because that’s the order you think about things. If you’re adding a new column to a table, you’ll want to make your code use it. If you run the migration first, that all works out nicely.
Migrations can be tricky, and it’s time-consuming to test them properly. One answer is to have other people look over your code.
In addition to the checks you can enforce with automated tools, there are a lot of things a human should look over. Let’s talk about some of the rules for code reviewing a migration that aren’t covered by the Good Migrations or Strong Migrations tools.
Keep Each Migration Small
Small migrations are (usually) happy migrations. It can be hard to roll back migrations, especially when they modify large tables. If your database supports rolling back schema changes at all, it can still take minutes or hours to do. Even a large, hard-to-divide operation like adding a column to a two-terabyte table is happiest if it’s mostly done by itself.
Remember that problem I had writing migration code where the whole site went down? Turns out I could have fixed that in advance by just following best practices for migrations.
Good Migrations is basically “don’t use models in your migrations.” It’s true, don’t. Most people already don’t, but Good Migrations enforces it.
Strong Migrations is “only use migrations that can run with no downtime and not screw anything up.” This may cramp your style a little more since you can’t do things like change the type of a column. There’s no safe way to do it, so Strong Migrations stops you.
You can learn a little more about why to be careful with these things from No More Lost Data, my book on migrations.
You can also learn more about the whys of migrations with no downtime here and in the book.
I might be a touch late, writing my 2015 end-of-year post in February.
It’s been a pretty good year in some ways, not a great one in others. First off, let’s hit some numbers:
- Rebuilding Rails revenue: $7478.82 on Stripe, $2269.00 on Gumroad
- Special summer sale revenue: $4500-ish
- Rails Deploy In An Hour revenue: $1683.30 (there may be more refunds happening, though.)
These are net of refunds, Stripe and Gumroad fees and so on.
That’s pretty decent Rebuilding Rails revenue, very much in line with the last two years. I also finally made the switch to Gumroad, so I’m not doing my own invoicing any more. The remaining chunk of time I spend on it week-to-week is debugging problems people hit with the software, and that shouldn’t go down much — the whole point is helping new people learn Rails. If they’re doing it right, they’re debugging. And talking programming with me isn’t something I can foist off on a remote assistant.
Andrew Kane of Instacart has a bunch of wonderful guides, including one on "strong migrations" — migrations that run without downtime on MySQL and Postgres. It sums up some wonderful previous articles about downtime-free migrations on Postgres with high data volume, how to create indices without downtime on Postgres, and no-downtime migrations in general.