@petecorey A huge mistake, but also a common mistake that probably everyone does once, whether they use Ecto, Alembic or Rails. 😊
Depending on what the language and framework allows, an alternative to not using the ORM at all is to define the required objects locally in the migration.
Rather than resorting to raw SQL I'm still quite in favor of using some abstractions in the application language that can be checked and composed with the usual tools, like the schemaless queries you mentioned.
One big question is *which* SQL. With a little bit of SQLAlchemy in my Alembic migrations I can stay compatible with both SQLite and PostgreSQL, even when using advanced datatypes.
12factors is nice and all, but it's also nice to have an in-memory db for certain integration tests.