Skip to content
BuildThenTestedSee packages

No index on the columns you filter by

Every message list, dashboard filter and row-level security check scans the full table, so pages slow down as data grows and the database CPU stays busy until queries start timing out. How the app behaves when there is more data or more users. Check it yourself with the steps below; our test adds what a script and a second account can find.

What it looks like

create table messages (
  id uuid primary key default gen_random_uuid(),
  conversation_id uuid references conversations(id),
  sender_id uuid references auth.users(id),
  created_at timestamptz default now()
);
-- queried constantly by conversation_id and created_at; no index on either
A table whose rows are always looked up by `conversation_id` and sorted by `created_at`, with no index on either column, so every query reads the whole table.

What happens

Every message list, dashboard filter and row-level security check scans the full table, so pages slow down as data grows and the database CPU stays busy until queries start timing out.

Where it shows up

Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.

Check it yourself

Uses your builder's dashboard and your browser. No tools to install.

  1. In the Supabase dashboard open Advisors, then Performance Advisor, and read the list of suggestions.
  2. Open Database, then Indexes, and note which of your busiest tables have indexes beyond the primary key.
  3. Compare with the columns your app filters by: anything ending in _id, plus user_id, status and created_at. For each busy table, check whether a matching index exists.

Bad result: the Advisor lists unindexed foreign keys or suggests new indexes, or your busiest tables show only the primary key index.

What we check

We run explain analyze (Postgres's report of how a query was executed) on the queries your pages actually issue, against a copy of your data scaled up. We list the sequential scans on filtered or joined columns and the row-level security policies that trigger them, with the index statement for each.

Fix direction

Add an index on each column used in where, join and order by on your busiest tables, starting with foreign keys such as user_id, and confirm with explain analyze that the planner uses it. Supabase's Index Advisor suggests candidates, and its docs note the planner may skip an index on small tables, so measure rather than index everything.

Mechanism documented in: Supabase: Managing Indexes in Postgres (verified 2026-09-21); Firebase: Manage indexes in Cloud Firestore (verified 2026-09-21).

Covered by

Full audit ($1,900, 5 business days)

Both include a re-check after your fixes.

Compare packages

Related patterns

  • One database query per list itemPerformance

    Pages that were fast with test data slow to a crawl as real data grows, the database handles hundreds of tiny queries per page view, and timeouts and higher hosting bills follow.

    Medium
  • List endpoints that return everythingPerformance

    As the table grows, the response gets slower and heavier until it hits a platform body-size or time limit and the page simply stops loading, usually for your biggest customer first.

    Medium
  • Whole table downloaded, filtered in the browserPerformance

    Every user's device downloads far more than it shows, so pages slow down as the table grows, and if the database does not also restrict rows, other people's records land in the browser.

    Medium
  • Any signed-in user can read every rowData access

    Anyone who creates a free account can page through every other customer's records, which is a data breach with a sign-up form as the only step.

    Critical

Questions

how do i know if my supabase table needs an index

Open the Performance Advisor in the Supabase dashboard; it flags foreign keys without an index and suggests others. Then look at the columns your app filters and sorts by, such as user_id or created_at, and check Database then Indexes for a matching entry. A table that is only ever fetched by primary key needs nothing more.

does rls make queries slow

Row-level security (RLS, the database rule that limits which rows each user can read) adds a condition to every query, such as user_id = auth.uid(). Without an index on user_id, the database checks that condition row by row across the table. Index the columns your policies compare against, then confirm the plan with explain analyze.

does firestore need indexes

Firebase's docs state that Cloud Firestore requires an index for every query, creates single-field indexes automatically, and returns an error with a link to create a composite index when a compound query needs one. So on Firestore the failure shows up as a query error during development rather than a slow scan in production.

Back to the catalogue, or run the self-check for your stack.