One file, one transaction, one related change
Past a single add_index, past a single table
"ActiveRecord: migrations" taught what a migration is. ActiveRecord migrations: indexes taught how to make a single add_index safe on a table that already holds real rows. Both stayed inside one operation on one existing table. Neither asked what happens when a feature needs several new tables at once, related to each other, that must land together or not at all. This course is about that "or not at all": what it buys, and what has to be true inside one migration file for it to hold.
The default this course relies on
The previous course's disable_ddl_transaction! opted a migration out of something that's there by default. Rails wraps an ordinary migration's whole change (or up) method in a single database transaction. This course never calls disable_ddl_transaction!, on purpose, because the property it removes is the one this course depends on.
What "one push" means
Picture a feature that needs a partners table and a partner_perks table that references it with a foreign key. This app built its partner feature in two files. 20260830200000_create_partners.rb created partners. A later file, 20260830210000_add_partner_perks.rb, added perk columns and created partner_course_sponsorships and partner_roles, both referencing partners. The examples in this course use a simpler, made-up partner_perks table with the same shape.
Write the two tables as one migration instead, inside Rails' default transaction. If a later statement fails, say a typo in a column type or a constraint that can't be met, PostgreSQL rolls back everything that ran before it. No partners table is left without its partner_perks, and no half-built schema is waiting for the next request to trip over. rails db:migrate either finishes the whole file or leaves the schema as it was.
Two separate files, run as two migrations, don't get this for free. If the first succeeds and the second fails, the first's changes are already committed for good. There's a partners table with no partner_perks, and someone has to notice and write a third migration to clean up. The transaction boundary is the file boundary, which is why related schema changes that must land together belong in one file.
Where this trades against the previous course
This is in direct tension with the previous course. algorithm: :concurrently needs the transaction gone, and this course's premise needs it present. One migration file can't have both an index built with algorithm: :concurrently and several related create_table calls that must land all or nothing, because disable_ddl_transaction! switches the whole file, not one statement. In practice the two rarely collide. The previous course was about adding one index to a large table that's already live. This course is about creating new, empty tables for a new feature, where the lock duration that worried ActiveRecord migrations: indexes doesn't apply yet: there's no data to block writes against.
Key takeaways
- "ActiveRecord: migrations" covered what a migration is, and the previous course covered making one
add_indexsafe on a live table. This course starts where both stop: several related schema changes that need to land together or not at all. - By default, Rails wraps an ordinary migration's
change/upin one database transaction. The previous course'sdisable_ddl_transaction!turns that off; this course relies on it staying on. - The transaction boundary is the file boundary. Related changes split across separate migration files don't get all-or-nothing behavior: if a later file fails, the earlier file's changes stay committed and orphaned.
- This course's premise and
algorithm: :concurrentlypull in opposite directions, one needing the transaction and the other needing it gone. That's usually fine, because they solve different problems: new, empty tables versus an index on a live one.
Keep going with lesson 2
Ordering: a table can't reference one that doesn't exist yet
A referenced table's create_table must come earlier in the file, or PostgreSQL raises PG::UndefinedTable.
A free account also gives you the quizzes, your progress and notes, and the discussion.