Running migrations on live databases with lots of data in them is hard. There are many strategies to work around this problem, but generally running an 'alter table' on your primary db server on a huge table while it is in use should be your very last option.
A staging system with a db server provisioned similarly to production lets you "smoke test" the migrations and deploy before you take down prod -- but especially with MySQL, that happily blocks all reads during an ALTER, you should really watch out for any table ~> 1M rows (or if they're wide, even fewer than that).
http://devcenter.heroku.com/articles/heroku-postgresql#fork_...
ALTER TABLE performance will eventually improve. PostgreSQL 9.1 lifts-off the lock-up limitation.
But what a performant ALTER TABLE will not improve is its intrusiveness to applications. When you change the schema you break the app.
That's the problem.
Most of the time migrations are developed in a feature branch, so the owner is responsible for splitting his branch into two or three before sending pull requests (as many as required to address issues with hot compatibility).
This means that we have two or more merges (and deploys) from master, each requiring a full run of the test suite.
The Percona pt-online-schema-change tool goes to great lengths to avoid this kind of problem.
I'd wager that a lot of the big professional rails deployments are doing FK constraints though.
This is because those projects typically sit on databases that are only expected to be accessed via web API and not directly from some other source.
Which is basically the Rails philosophy. Only let the app talk to the DB, and let the only outside interface to the DB be through the ORM that has to do most of the data validations anyway.
[1] https://github.com/soundcloud/large-hadron-migrator
Edit: URL
I'd also recommend using South for migrations http://south.aeracode.org/