No index on the columns you filter by
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 eitherWhat 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.
- In the Supabase dashboard open Advisors, then Performance Advisor, and read the list of suggestions.
- Open Database, then Indexes, and note which of your busiest tables have indexes beyond the primary key.
- Compare with the columns your app filters by: anything ending in
_id, plususer_id,statusandcreated_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).
Related patterns
- One database query per list itemPerformanceMedium
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.
- List endpoints that return everythingPerformanceMedium
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.
- Whole table downloaded, filtered in the browserPerformanceMedium
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.
- Any signed-in user can read every rowData accessCritical
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.
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.