Multi tenant app. Headers
Hi,
I would like to create a header
x-org-id that the supabase sdk sents for every request using the DataAPI? Is this possible and can I use this in RPCs and RLS policies?
If not I could also sent it as a param to RPCs instead but dont think I have a way to use that as hint in RLS unless I write to a table that has a org Id column.18 Replies
Yes. You can set a header when you createClient and RLS and rpc can see it.
https://docs.postgrest.org/en/v13/references/transactions.html#request-headers-cookies-and-jwt-claims
Make sure you test storage and realtime if you need it it there for RLS. Pretty sure it works for storage, but can never remember.
Is it psosible to set the header after createClient? I only know the org id after my get profile with settings RPC loads which of course needs a client
Ah yeah dont think realtime will work at all tbh
I don't know of a method after createClient.
Really unfortunate that I cant do per client custom claims. Custom claims are normally the go to way but it wont work in this case because if the same auth user wants to check org A on their phone and org B on their laptop it will break after a refresh
Do you think Realtime will break if RLS are dependend on a header from the client?
I thought Realtime RLS are done without a connection to the client, besides the websocket.
I do not remember. I'm sure it would show up in issues. Storage and Realtime do not use postgREST so they do their own "faking" of what PostgREST does for RLS.
I've used this hacky code to change headers and schema in the past (before there was a .schema() option.
But no idea if it is production worthy.

Ah I see, I think for now I will let RLS do a little bit extra work and just get everything cross tenants. This seems relativly easy to implement after release. And I missed multiple deadlines already haha
I really feel like a idiot, the project is feature complete. But I realized I made a really stupid decision, I thought it would be a good idea to have each tenant have its own supabase project. But this is a nightmare to manage. So just before when i wanted to release I figured, let's do multi tenant
If i started with that from the start I didnt have to refactor 100+ files...
It would be a nightmare to manage dozens of projects that need similar code bases.
Yeah exactly, I did write a CD to push migrations for multiple projects, but what if one fails, or one slows down because of some edge case. You can never monitor all of them. But honestly developing is 50% coding and 50% architecting, and just like bugs in code, sometimes you make a architectural mistake.
I see storage PR that says it was implemented.
Happy I catched it before release, because after it would have been tedious to merge all DBs
Ah thats nice, thanks for checking it out.
Do you have some tips on things I should checkout before I release that should be good, besides all security things. Like things that are tedious to fix when you have data since migrations for that are hard.
I think going from siloid to multi tenant is the worse so happy I am fixing it now in a week instead of after release in a month.
Is there something else.
I was thinking maybe partition some tables that grow fast, since that isnt really fun if you already have non partitioned data.
Most don't mess with partitioned tables until they millions of rows.
Make sure you follow the RLS tuning docs if you are accessing other tables in the RLS to determine which tenant.
Yeah I learned that lesson already, sub queries are killers haha
Yeah true but I have 2 tables that I know will grow really fast. For groups, profiles etc I won't even bother. Don't think they will even reach a million since groups older than 4 years get deleted automatically..
But for the task table I expect each user to create 3 on average a day
So with 1k users I am already over a million
https://github.com/supabase/realtime-js/issues/233
I'd say realtime is iffy on custom header.
GitHub
Custom Headers not present in RLS · Issue #233 · supabase/realtim...
Bug report I confirm this is a bug with Supabase, not with my own application. I confirm I have searched the Docs, GitHub Discussions, and Discord. Describe the bug Custom header in Supabse SDK are...
From our resident PG guru user... https://discord.com/channels/839993398554656828/1360215966063132682/1361392300000940033
Ah I see thanks
Do you think it's worth to do partitioning upfront or would you say just let it be and if time comes, it won't be that hard to partition existing rows
Never done this in prod, seems like I need to make a migration that creates the partitions, and manually insert the data and delete from the unpartitioned one. Doesn't seem hard, but let's say I have 20m rows. Won't I have issues with timeluts and stuff.
Sorry not something I've ever done including multitenant with postgres.
Ah okay well thanks again!