From 9e5183fc52b3d07e842779d0156644e5c0003b86 Mon Sep 17 00:00:00 2001 From: Dmitry Maranik <40249835+dmitrymaranik@users.noreply.github.com> Date: Mon, 29 Jun 2026 15:01:56 -0700 Subject: [PATCH] perf(rls): wrap auth calls in (select ...) for per-statement eval --- .../20260629150153_wrap_rls_perf_initplan.sql | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 supabase/migrations/20260629150153_wrap_rls_perf_initplan.sql diff --git a/supabase/migrations/20260629150153_wrap_rls_perf_initplan.sql b/supabase/migrations/20260629150153_wrap_rls_perf_initplan.sql new file mode 100644 index 0000000000..7106e8e2ff --- /dev/null +++ b/supabase/migrations/20260629150153_wrap_rls_perf_initplan.sql @@ -0,0 +1,34 @@ +-- Wrap auth.uid()/current_setting() in RLS policy predicates in (select ...) so +-- Postgres evaluates each once per statement (an InitPlan) instead of once per row -- +-- the Supabase-documented RLS perf pattern. Covers USING and WITH CHECK. Predicate- +-- equivalent (row visibility unchanged). Generated by 'pgrls fix --rule PERF001' +-- (pgrls 0.44.0) and verified on Postgres 16 (PERF001 -> 0). + +-- [PERF001] Wrap auth function call(s) in policy 'Enable read access for all users' on public.layout so Postgres can cache the result for the whole statement instead of re-evaluating per row. +ALTER POLICY "Enable read access for all users" ON public.layout + USING (user_id = (SELECT auth.uid())) + WITH CHECK (user_id = (SELECT auth.uid())); + +-- [PERF001] Wrap auth function call(s) in policy 'Enable delete access for auth users' on public.user_api_keys so Postgres can cache the result for the whole statement instead of re-evaluating per row. +ALTER POLICY "Enable delete access for auth users" ON public.user_api_keys + USING ((SELECT auth.uid()) = user_id); + +-- [PERF001] Wrap auth function call(s) in policy 'Enable inserts for users based on user_id' on public.user_api_keys so Postgres can cache the result for the whole statement instead of re-evaluating per row. +ALTER POLICY "Enable inserts for users based on user_id" ON public.user_api_keys + WITH CHECK ((SELECT auth.uid()) = user_id); + +-- [PERF001] Wrap auth function call(s) in policy 'Enable read access for all users' on public.user_api_keys so Postgres can cache the result for the whole statement instead of re-evaluating per row. +ALTER POLICY "Enable read access for all users" ON public.user_api_keys + USING ((SELECT auth.uid()) = user_id); + +-- [PERF001] Wrap auth function call(s) in policy 'Enable read access for users' on public.user_api_keys so Postgres can cache the result for the whole statement instead of re-evaluating per row. +ALTER POLICY "Enable read access for users" ON public.user_api_keys + USING ((SELECT auth.uid()) = user_id); + +-- [PERF001] Wrap auth function call(s) in policy 'Enable insert access for all users' on public.user_settings so Postgres can cache the result for the whole statement instead of re-evaluating per row. +ALTER POLICY "Enable insert access for all users" ON public.user_settings + WITH CHECK ((SELECT auth.uid()) = "user"); + +-- [PERF001] Wrap auth function call(s) in policy 'Enable read access for all users' on public.user_settings so Postgres can cache the result for the whole statement instead of re-evaluating per row. +ALTER POLICY "Enable read access for all users" ON public.user_settings + USING ((SELECT auth.uid()) = "user");