VibeGuard
Guides

Why your Supabase bill spikes after adding RLS

RLS predicates run against every candidate row. Two mistakes make that catastrophic, and both look completely correct when you read the policy.

Rules that check this

The predicate column has no index

A policy filtering on `user_id` with no index on `user_id` degrades every query into a sequential scan of the whole table. It is invisible at a thousand rows and ruinous at a million.

VibeGuard reports one finding per table and column rather than per policy — three policies filtering the same column need one index between them, and three alerts would be three times the noise for one fix.

CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_invoices_user_id
  ON public.invoices (user_id);

auth.uid() is called per row

A bare `auth.uid()` inside a policy is re-evaluated for every candidate row. Wrapping it in a scalar subquery lets the planner hoist it into an InitPlan evaluated once per statement.

The semantics are identical. On tables past a few thousand rows the difference is routinely ten to a hundred times.

-- Before: evaluated per row
USING (auth.uid() = user_id)

-- After: evaluated once per statement
USING ((SELECT auth.uid()) = user_id)

Correlated subqueries count too

A call inside `EXISTS (SELECT 1 FROM members WHERE user_id = auth.uid())` is still per-row, because that subquery is correlated. VibeGuard flags it, and the fix is the same wrap.

Frequently asked

Why CONCURRENTLY?
It avoids taking a write lock on a live table. It cannot run inside a transaction block, so run that statement on its own.
Does a composite index count?
VibeGuard treats a column as covered if it appears in any valid index key. A leading position serves the predicate best, but demanding one produces more noise than it prevents.
Is this a security issue?
No, it is a cost and latency issue, which is why it is reported as medium rather than critical. It is the most common reason a Supabase bill grows faster than traffic.

Check your project in about ten seconds

Paste a URL. No signup, no writes, nothing stored.

Run the free audit
unindexed rls policy supabasesupabase rls performance slowauth.uid() initplan optimizationwhy is my supabase bill spiking after adding rls policies