Catch Unsafe Migrations With The Strong Migrations Gem

It is possible to do database migrations without incurring any downtime as long as we follow certain patterns. For example, instead of renaming a column (which is not backwards-compatible with currently running web servers) in one step, you would so in 3 steps:

  1. Add the new column and start writing to both columns but keep reading from the old column
  2. Sync the new column with the old and stop writing to the old column
  3. Drop the old column

A very useful tool in this context is the Strong Migrations gem. This gem will detect potentially unsafe migrations and prevent them from running. It will even give you some guidelines on safer ways to do what you want!

 __          __     _____ _______ _
 \ \        / /\   |_   _|__   __| |
  \ \  /\  / /  \    | |    | |  | |
   \ \/  \/ / /\ \   | |    | |  | |
    \  /\  / ____ \ _| |_   | |  |_|
     \/  \/_/    \_\_____|  |_|  (_)  #strong_migrations

ActiveRecord caches attributes which causes problems
when removing columns. Be sure to ignore the column:

class User < ApplicationRecord
  self.ignored_columns = %w(some_column)
end

Once that's deployed, wrap this step in a safety_assured { ... } block.

More info: https://github.com/ankane/strong_migrations#removing-a-column

If you’re sure a migration is safe - for example, if you’re dropping a column as the 3rd step of renaming a column - you need to wrap your migration in a safety_assured block.

class MySafeMigration < ActiveRecord::Migration[5.2]
  def change
    safety_assured { remove_column :users, :some_column }
  end
end

I really like this since it’s an obvious conversation point during code reviews. It’s not going to catch all errors, but it’s a great tool - it adds value without any real overhead.