Safer ActiveRecord migrations for Postgres
- stars
- 117
- watchers
- 82
- forks
- 8
- open issues
- 4
- Last updated
- 07/23/2026
Safer ActiveRecord migrations for Postgres
Looking for Rails 4.0 or Ruby 2.0 support? Please check out the 1.x tree.
Note: this library only supports PostgreSQL 9.3+. If you're interested in adding support for other databases, we're open to pull requests!
Postgres holds ACCESS EXCLUSIVE locks for almost all DDL operations. ACCESS EXCLUSIVE locks conflict with all other table-level locks, which can cause issues in several situations. For instance:
Both these issues can be avoided by setting timeouts on the migration connection -
statement_timeout and lock_timeout respectively.
Once this gem is loaded, all migrations will automatically have a
lock_timeout and a statement_timeout set. The initial lock_timeout
default is 750ms, and the initial statement_timeout default is 1500ms. Both
defaults can be easily changed (e.g. in a Rails initializer).
ActiveRecord::SaferMigrations.default_lock_timeout = 1000 ActiveRecord::SaferMigrations.default_statement_timeout = 2000
To explicitly set timeouts for a given migration, use the set_lock_timeout and
set_statement_timeout class methods in the migration.
class LockTest < ActiveRecord::Migration set_lock_timeout(250) set_statement_timeout(750) def change create_table :lock_test end end
To disable timeouts for a migration, use the disable_lock_timeout! and
disable_statement_timeout! class methods. Note that this is extremely
dangerous if you're doing any schema alterations in your migration.
class LockTest < ActiveRecord::Migration # Only do this if you really know what you're doing! disable_lock_timeout! disable_statement_timeout! def change create_table :lock_test end end
This gem sets session-level settings on Postgres connections. If you're using PgBouncer in transaction pooling mode, using session-level settings is dangerous, as you can't guarantee which connection will receive the setting. For this reason, this gem is incompatible with transaction-pooling and should only be used if migrations are run on connections that support session-level features.