Database as Code – The Good, the Bad and the Ugly
bytebase.com
bytebase.com
Teams need GitLab / GitHub to collaborate instead of relying on Git merely.
It's not about pretty UI and more about UX / DX around dealing with database migrations like how GitLab / GitHub deals with code changes.
And Flyway can be used in conjunction with GitLab/GitHub to achieve the same thing, but it's still plagued with all of the issues you can probably imagine, especially if your DB doesn't support transactional DDLs.
I agree about how these database migration (i hate this name) tools are starting to show their age, but when it comes to read/write schemas there doesn't seem to be many options.
If you're wondering why I qualified the above statement with "read/write", there is an alternative way of managing read schemas that has a lot in common with any other sort of artifact management lifecycle that we have become accustomed to. Every source change that results in a CI/CD activity leads to an entirely new instance of the schema being built out. Then it's just a matter of hot swapping the new schema (`ALTER SCHEMA ACME SWAP WITH ACME_V2_0 RENAME TO ACME_V1_9_OLD`) or just having your consumers update their connection configurations to point to the new schema (schema=ACME_V2_0). Rollback is just unswap, or reverting your app's connection config (or maybe the software artifact should be hard tied to the schema anyways?).
The whole process of using a migration tool to alter individual parts of a live schema one piece at a time, updating/data, etc... and rollback if necessary, is extremely complex and an incredible nightmare to deal with, esp if these tools are in the hands of app developers with limited DBA experience.
Imagine that if instead of building new code artifacts (jar, zip, etc) we just resorted to taking the latest one, modifying it, and then saved it (overwrite). And then when you experience an issue and have to rollback, you have to undo everything mentioned above.
Completely obsoletes any other tools and makes building up a new database (e.g. for test instances etc) an easy order. Are there cases where this can't be applied in new projects?
[1] For an example, see https://github.com/mozilla-services/syncstorage-rs/tree/mast... in combination with https://github.com/mozilla-services/syncstorage-rs/blob/mast...
In practice they often do take a significant amount of discipline at multiple different stages. And they need to account for schema changes outside of perfectly defined and reviewed migrations, because those do happen.
Or you can so "no those can't happen" but that discipline comes at a cost too. Outages and incidents happen, and sometimes the resolution of them will be an on the fly index or other schema change. Does the migration tool give you anything to manage that? Did anyone remember to run it to generate the schema diff and apply it to the other dbs?
And sure you can say "don't resolve incidents with out-of-migration schema changes" but that has costs too. You're going to add process, and time, both when you do it and before in defining and documenting these processes.
ORMs and/or their migration tools is the solution to this, but it isn't a perfect, easy solution. It tends to be fragile over time in the face of day to day changing requirements, as you generally have in a small startup-type company. It's only a solved problem from a purely technical standpoint. In practice every company I've seen has had at least some problems with this, or mountains of careful process to avoid it. Tradeoffs either way.
Generally you always want to ensure your application logic works properly with both the current schema and next schema. This way, you can roll out the schema change independently first, and then only if/when it succeeds, you roll out new application code (and/or enable new feature flags etc) which actually uses the new columns, tables, procs, etc.
If you tie the schema change to the app deployment instead, you have to do the opposite: ensure that the new version of the application is backwards-compatible with the old schema. That's necessary because you probably have multiple copies of an application running (for HA), and some schema changes may take a long time to run.
So upon deploying a new version of your application, even if your modern ORM correctly handles migration locking (to ensure only one app copy runs the migration), you would still have a window where other updated app servers are running updated code but the schema hasn't been changed yet. So if you tie schema changes to app deployments, the app must be backwards-compatible with the old schema: every single reference to a new database object must be gated with a feature flag, every time.
In contrast, the decoupled deploy / forwards-compatible approach is much easier, because generally application code already won't interact with database objects that the code doesn't know about.
Also he has written a few other articles about databases very recently too https://sive.rs/blog
I'm pretty sure the core migration functionality provided by knex is supported -- along with some project specific features which support more modular schema migrations via batches of SQL files held within specific directories.
Shameless plug... sure. But it may be useful to anyone interested in the topic of this post.
https://github.com/sudowing/service-engine-template#schema_m...