Context
We do schema-based multi-tenancy in our Postgres DB. Each and every schema is associated to a different tenant and will have the exact same structure except for one schema named public
.
To obtain the list of all the relevant schemas, we can use:
SELECT tenant_schema FROM public.tenant_schema_mappings;
Problem
We need to periodically clean up a specific table for all the tenants:
DELETE FROM a_tenant_schema.parent WHERE expiration_date_time < NOW();
(The actual query is a bit more complex because we need to also delete the linked children
entries associated with the parent
, but let us keep things simple for the sake of this question.)
Constraints
- We cannot use
pg_cron
because our DB server is hosted on Azure, and that extension isn't supported yet. - We do not want to deploy an entire service/application just to execute a cron job.
- We have thus decided to use a
CronJob
pod deployed within our k8s namespace and can thus communicate directly with the DB using thepsql
client via shell commands.
Question
What would be the best way to execute the given DELETE
statement against all of the relevant schemas using psql
in the shell?
Please keep in mind: since there may potentially be hundreds of tenants, it could be interesting to run the clean up queries for each tenant in parallel.
Current potential solutions
So far there seems to mostly be 2 approaches that could be interesting (although I'm not quite sure how to parallelize the query execution):
- Figure out how to do everything from within a single Stored Procedure and simply call that SP using
psql -c
. - Use
psql -c "SELECT tenant_schema FROM public.tenant_schema_mappings;"
to gather the list of all relevant tenant schemas, and then use shell commands to iterate through that list by dynamically constructing the appropriate queries. With the result set of queries, run them all one by one usingpsql -c
.
Other partial solution
I've figured we can actually construct the queries using the following SQL:
SELECT 'DELETE * FROM ' || tenant_schema || '.parent WHERE expiration_date_time < NOW();' AS query
FROM public.tenant_schema_mappings;
Maybe there would be a way to tell Postgres to execute all of the resulting strings?