Also great work on Alembic, I started using it a few weeks ago and am very pleased.
Some of the other constraints you'll have to implement in your software. The advantage: you don't put application logic outside of your application. The disadvantage: Every bit of code touching that value has to know the limitations. I wonder if this could be solved by using a message queue and just have dedicated step for updating/deleting data
See but now you're building some big thing. Let's just include that in MongoDB or whatever, a "constraints engine". So that you don't have to build it from scratch each time, and can have some mature, well tested thing instead of something ad-hoc and probably buggy. Now you need to carefully build migrations again !
What's worse than migrations? Being unable to turn an application off, since it uses the old schema.
With ChronicDB we support indefinite backward compatibility. Unlike per-record versioning tricks, application code does not need to be aware of migration code.
each version migration is a function that takes a record in an old state a migrates it to a new one.
once you read a record from the db that has an outdated version number you run all the pending migrations and then save.
with this scheme your application code only has to know how to deal with the latest schema version. all the rest is handled by migrations.
A convention-based approach, or even a well thought out data-enforcement approach, will have bugs and failures, and you just have to hope these failures aren't severe enough that you lose your "one" chance.
Relational constraints OTOH when used in their usual way make it virtually impossible to have situations like this.
Of course constraints are tedious when you're in "experimentation" mode (to quote another post I see here) and are doing rapid, early development. But once you're in production with data that's critical/important (i.e., not someone's list of their favorite songs; more like, their bank statements and medical histories), constraints are the bees knees.
Once you have data constraints in place, now migrations are hard - whether or not you're on a SQL database. You need to either update all old documents to match new schemas, or open up your constraints to "expect both" (where by "both" I really mean, "any number of 18 different formats...oh make that 19") - and that is the potentially slippery slope here into a coding crapfest.
Disclaimer: I'm the author of a very popular SQL tool for Python (SQLAlchemy) as well as a new database migrations tool (Alembic).