> As I've hinted at before, migrations should be functions. Functions as in "a function written in a programming language", not functions as in "SQL snippets I just refer to as functions because it makes me sound smart".<p>Disagree. SQL is a declarative language that is both clear and universal. Feel free to generate the migrations however you’d like, but I want to see the SQL.<p>Another bonus (and I’m sure I’ll be told I’m wrong) is that you don’t need to write tests for the migration, because it’s declarative. Assuming you know what it means (if you don’t, maybe you shouldn’t be administering a DB) and what its locking methods entail, you will get _precisely_ what it says, and nothing more. If you get a failure from, say, a duplicate entry when creating a UNIQUE constraint, that’s orthogonal to the migration itself – you described the end state, the DB tried to make that happen, but was unable to do so due to issues with your data. All the tests in the world wouldn’t catch that, short of selecting and deduping the column[s], and at that point, you’re just creating work.<p>I am firmly convinced that any and all infrastructure should be declaratively instantiated, and declaratively maintained. I do not want or need to test my Terraform files, nor my DDL.