Problem
Currently, PostgREST can dynamically add new schemas at runtime, but selecting which schema a request hits still requires the client to specify it via Accept-Profile or URL. This exposes schema names to clients and makes fully hidden multi-tenant routing impossible.
What I tried
I configured PostgREST to use a pre-request function:
create or replace function postgrest.set_schema_from_jwt()
returns void as $$
declare
schema_name text := current_setting('request.jwt.claims', true)::json->>'namespace';
begin
if schema_name is not null and schema_name <> '' then
perform set_config('search_path', schema_name, true);
else
raise exception 'Invalid or corrupted JWT';
end if;
end;
$$ language plpgsql;
And set it in the environment:
PGRST_DB_PRE_REQUEST="postgrest.set_schema_from_jwt"
However, this does not work for routing endpoints because it runs after PostgREST has already planned the query. Changing search_path at this point only affects functions or views, not which schema the endpoint resolves to.
Use case
- Each tenant has its own schema
- JWT contains the tenant identity or role (e.g.,
"namespace": "schema_fd9d")
- Requests should automatically go to the correct schema based on the JWT, without the client needing to set headers or URLs
Proposed feature
Add a configuration option, e.g.:
db-schema-claim = "namespace"
Behavior:
- PostgREST reads the configured JWT claim before routing
- Uses its value as the API schema for the request (like
Accept-Profile)
- Falls back to a default schema if the claim is missing or invalid
Benefits
- Supports fully hidden multi-tenant routing
- No need for clients to send headers
- Works with dynamically added schemas
- Keeps schema cache and OpenAPI generation deterministic
- Compatible with JWT-based access control
Security considerations
- JWT claims are signed and verified, so schema selection is trusted
- Permissions still follow the role grants, same as current behavior
Problem
Currently, PostgREST can dynamically add new schemas at runtime, but selecting which schema a request hits still requires the client to specify it via
Accept-Profileor URL. This exposes schema names to clients and makes fully hidden multi-tenant routing impossible.What I tried
I configured PostgREST to use a pre-request function:
And set it in the environment:
However, this does not work for routing endpoints because it runs after PostgREST has already planned the query. Changing
search_pathat this point only affects functions or views, not which schema the endpoint resolves to.Use case
"namespace": "schema_fd9d")Proposed feature
Add a configuration option, e.g.:
Behavior:
Accept-Profile)Benefits
Security considerations