I have a web application that is built using Pyramid / SQLAlchemy / Postgresql and allows users to manage some data, and this data is almost completely independent for different users. Say Alice visits alice.domain.com and can upload photos and documents, and Bob visits bob.domain.com , and can also upload photos and documents. Alice never sees anything created by Bob and vice versa (this is a simplified example, in fact there can be a lot of data in several tables, but the idea is the same).
Now the easiest way to organize data in the database of the database server is to use a single database, where each table ( pictures and documents ) has a user_id field, therefore, basically, to get all Aliceβs photos, I can do something like
user_id = _figure_out_user_id_from_domain_name(request) pictures = session.query(Picture).filter(Picture.user_id==user_id).all()
All this is easy and simple, but there are some disadvantages
- I need to remember that you always need to use the additional filter condition when executing queries, otherwise Alice can see Bob's photos;
- If there are many users, tables can grow huge
- It can be difficult to split a web application between multiple machines.
So, I think it would be very nice to somehow share the data for each user. I can imagine two approaches:
There are separate tables for photographs and documents of Alice and Bob in one database (Postgres Schemas , apparently, is the right approach to use in this case):
documents_alice documents_bob pictures_alice pictures_bob
and then, using some dark magic, βlay outβ all queries in one or another table in accordance with the current query domain:
_use_dark_magic_to_configure_sqlalchemy('alice.domain.com') pictures = session.query(Picture).all() # selects all Alice pictures from "pictures_alice" table ... _use_dark_magic_to_configure_sqlalchemy('bob.domain.com') pictures = session.query(Picture).all() # selects all Bob pictures from "pictures_bob" table
Use a separate database for each user:
- database_alice - pictures - documents - database_bob - pictures - documents
which seems like a clean solution, but I'm not sure that multiple connections to the database will require much more RAM and other resources, which will limit the number of possible βtenantsβ.
So the question is, does everything make sense? If so, how do I configure SQLAlchemy to dynamically change table names for each HTTP request (for option 1) or to maintain a pool of connections to different databases and use the correct connection for each request (for option 2)?
python postgresql sqlalchemy multi-tenant
Sergey
source share