Why does this code work as 2 separate migrations, but not as a single one?

It very well might be transaction related (everything in change is indeed run inside one). If you ever need to commit a transaction in a migration you can use the flush() function. However, @iarekk, you really shouldn’t put schema names in migrations. If the schemas ever change in a way that older migrations don’t expect, they will break. It’s actually best to keep data migrations complete out of migrations and use a different solution but if you do, they should be written as raw SQL: execute("update users u set username = u.email") and best written as separate migrations anyway so they can be deleted once they’ve been run in production.