Database migrations are the tricky part of any deployment. They make zero-time deploys problematic. They requires special attention since they can break stuff. Some might choose to run migrations automatically, some of us run them manually. But one thing is almost always true; the production code without migrations should not ever run. So how not to run your code without doing migrations first?
In the project I am working on we have our production processes defined in a file called
Procfile. It can look like this:
web: bundle exec puma -C config/puma.rb worker: bundle exec sidekiq -C ./config/sidekiq.yml ...
So we have a standard Puma process serving the requests and one Sidekiq worker process. Both should not run any code without migrations since something could go horribly wrong.
To check for migrations in Rails we can run
ActiveRecord::Migration.check_pending!. And we need to run it somewhere during the boot/initialization. In my case I can put the code in an initializer and limit the check for these two production processes:
if ($PROGRAM_NAME.include?('puma') || $PROGRAM_NAME.include?('sidekiq')) && Rails.env.production? ActiveRecord::Migration.check_pending! end
And that’s it! If anybody tries to run it it will scream! Helpful when doing manual migrations with Dokku where the container might start automatically.
← IT'S OUT NOW
I wrote a complete guide on web application deployment. Ruby with Puma, Python with Gunicorn, NGINX, PostgreSQL, Redis, networking, processes, systemd, backups, and all your usual suspects.