Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL schema design with foreign key constraint for tenants

I am designing a database for use in a multi-tenant scenario. I have recently learnt that in order to enforce that tenant_ids are consistent among tables that reference each other, I need to have the primary key of the tables to include both the table id and also the tenant_id. The foreign keys then have to reference both the table id and also the tenant_id.

This seems to be working as intended, but what if I have tables that don't reference the tenant? In my example below I have a playlist_item that doesn't reference the tenant directly. A problem I see here is that the playlist_item potentially might reference a piece of content that does not have the same tenant as the playlist it belongs to.

A possible solution would be to also include the tenant_id into all tables that exists in the database in order to be able to reference the tenant all the time, but this seems a bit cumbersome to me because the playlist_item (in this case) already has an implied tenant_id thru its owner relationship with playlist.

I would appreciate some insight into what would be a good solution in this case, and also if there are any alternative ways of achieving the same goal without potential risks of inconsistent data.

(This is just a sample, not the actual database)

Sample schema design

like image 930
Patrik Avatar asked Sep 12 '25 01:09

Patrik


1 Answers

You have two basic options here.

The first is to add additional foreign keys and unique constraints which include a tenant_id and if you do this you can ensure that the same tenant is referenced across the board. Do this if you want to use row-level security policies because it will solve a bunch of performance problems in checking security.

In this case playlist would have a second unique index on (id, tenant_id) and playlist_item would have a foreign key on (playlist_id, tenant_id) referencing that.

Your second option is to drop the tenant_id where it is transitively referenced. In this case you can always look it up via a join, but this performs poorly when tying to use row-level security.

like image 121
Chris Travers Avatar answered Sep 13 '25 16:09

Chris Travers