- we end up with many slightly different integrations, written by different people or even the same person at different points in time.
Ironically, our attempt at avoiding tech debt has caused us more tech debt.

One approach could be to build your data-models as a dedicated python module.

I mean different implementations of the integration between SQLAlchemy and Flask, in our applications. Not different implementations of the models, as each app has its own and that's expected.
I'm talking about the setting up of the DB, reading the URI from the config file, the script that calls MetaData.create_all() and then alembic.commands.stamp(), the creation of the session, the removal of the session when the request is done, the activation of foreign keys on SQLite, ways to check that the schema is up-to-date, etc etc. All this stuff that all of our DB-using apps need, and almost all of them have done differently.
 
Also you might want to check how deep SQLAlchemy is tied to your project (model, relationship, backrefs, sub_query, join, clause function, sesion, bulk_insert, etc) to see if this is such a big deal.

I think it's very very tied to the applications. You'll find SQLAlchemy-specific code in the model methods and in the views, but the app is also usually manipulating the model instances, calling their attributes on-demand, etc.
 
Do all the apps require relational db or not, or even at which percent?

I think a lot of them do, I'd say that non-DB using web apps are the exception (like webhook2fedmsg handlers)
 
I use since a while Aiohttp coupled with aiohttp-slqalchemy. those two work pretty well.
might want to look them up.

Interesting, I haven't tried those two. I don't suppose it lets you use SQLAlchemy's transparent attribute access in a non-blocking way? For example when calling Child.parents, SQLAlchemy will emit a query and populate the parents attribute with the result list, but that's a DB query and in the async world it should not block.
 
Thanks!

Aurélien