MoneyForward Developers Blog



My favorite gem: Strong Migrations

This article is a part of MoneyForward Tech Blogathon 2022.

Hello, I'm pocke. I work for Accounting Plus (クラウド会計Plus) as a Web Backend Engineer. I work as a Ruby Committer to maintain RBS too.

Today I'll introduce a gem, strong_migrations, which is my favorite gem.

This article was originally written in Japanese, and I translated it myself.

What is strong_migrations

strong_migration is a gem to detect dangerous migrations.

Database migration can often be dangerous. For example, it blocks writing to the database depending on DDL. Changing table definitions may cause unexpected behavior on your application.

This gem detects such dangerous migrations.

How to use

It's easy. Add strong_migrations to your Gemfile, then execute bundle install and bin/rails generate strong_migrations:install.

Only with the above processes, dangerous migrations fail automatically by this gem.

If you want to suppress the error, you can wrap the migration with safety_assured { add_column ... } block.

Problems detected by strong_migrations

All of the problems are listed in the README. For example, deleting a column and adding a column with a default value are good examples to understand this gem.

This gem is for a Rails application, but the most checked problems are RDBMS problems, which don't depend on Rails. I recommend looking at the problems list even if you do not develop Rails applications.

Why strong_migrations is great

Detecting dangerous migrations is valuable, but personally, I think it is the most valuable part of this gem. The most valuable part is the detailed descriptions.

Let's look at the error message of adding a column with a default value. The following code causes an error by Strong Migrations.

class AddTitleToArticle < ActiveRecord::Migration[7.0]
  def change
    add_column :articles, :title, :string, default: ''

The error message is the following.

=== Dangerous operation detected #strong_migrations ===

Adding a column with a non-null default blocks reads and writes while the entire table is rewritten.
Instead, add the column without a default value, then change the default.

class AddTitleToArticle < ActiveRecord::Migration[7.0]
  def up
    add_column :articles, :title, :string
    change_column_default :articles, :title, ""

  def down
    remove_column :articles, :title

Then backfill the existing rows in the Rails console or a separate migration with disable_ddl_transaction!.

class BackfillAddTitleToArticle < ActiveRecord::Migration[7.0]

  def up
    Article.unscoped.in_batches do |relation| 
      relation.update_all title: ""

As you can see, the error message is very detailed. This message includes the following items.

  • What is the problem.
  • Why the problem will cause.
  • How should you treat this problem.

In this message, the three items correspond to the following sentences.

  • WHAT: Adding a column with a non-null default
  • WHY: It blocks reads and writes while the entire table is rewritten
  • HOW: The suggested code snippets

The user can easily understand the problem and how to solve it through this message. If you got the message, you could solve the problem only with the message. No google is needed in many cases.

Such tools tend to have not enough messages, but this gem displays enough messages to solve the problem. I want to follow this style when I create such a tool.


I introduced the strong_migrations gem. You can install this gem easily, and you'll gain safety migrations.

I also describe the kindness of this gem. I love this gem because of its kindness.

Let's install this gem to your Rails application!

マネーフォワードでは、エンジニアを募集しています。 ご応募お待ちしています。

【会社情報】 ■Wantedly株式会社マネーフォワード福岡開発拠点関西開発拠点(大阪/京都)

SNS】 ■マネーフォワード公式noteTwitter - 【公式】マネーフォワードTwitter - Money Forward Developersconnpass - マネーフォワードYouTube - Money Forward Developers