Severity: High
Labels: performance, backend, P1
Location:backend/db/supabase_schema.sql:119-126 (no index on messages); query sites backend/routes/learn.py:300-304, :324-328, :805-809 (filter session_id, order created_at.asc).
Description
Every message read filters by session_id and orders by created_at, but messages has no index (the FK to sessions(id) does not create one in Postgres). Loading a chat session — history reconstruction and get_session — sequentially scans and sorts the entire messages table, which grows one row per chat turn (the fastest-growing table in the app).
Steps to reproduce
N/A (performance). EXPLAIN the session-history query as messages grows.
Expected vs actual
- Expected: indexed range scan by
(session_id, created_at). - Actual: full scan + sort on every chat load.
Suggested fix
CREATEINDEXIF NOT EXISTS idx_messages_session_created ON messages(session_id, created_at);
Acceptance criteria
- The session-history query uses the index (verified via
EXPLAIN). - Index added to
supabase_schema.sql + migration.
Severity: High
Labels: performance, backend, P1
Location:
backend/db/supabase_schema.sql:119-126(no index onmessages); query sitesbackend/routes/learn.py:300-304,:324-328,:805-809(filtersession_id, ordercreated_at.asc).Description
Every message read filters by
session_idand orders bycreated_at, butmessageshas no index (the FK tosessions(id)does not create one in Postgres). Loading a chat session — history reconstruction andget_session— sequentially scans and sorts the entiremessagestable, which grows one row per chat turn (the fastest-growing table in the app).Steps to reproduce
N/A (performance).
EXPLAINthe session-history query asmessagesgrows.Expected vs actual
(session_id, created_at).Suggested fix
Acceptance criteria
EXPLAIN).supabase_schema.sql+ migration.