Skip to content

perf(scans): add compound index on (repo_owner, repo_name, status, created_at DESC) - #23

Merged
davidstrouk merged 1 commit into
mainfrom
perf/scans-compound-index
Apr 24, 2026
Merged

davidstrouk merged 1 commit into
mainfrom
perf/scans-compound-index

Conversation

@davidstrouk

Copy link
Copy Markdown
Collaborator

Closes #22.

Summary

  • Adds a btree index on scans (repo_owner, repo_name, status, created_at DESC).
  • Matches the exact predicate + ORDER BY of the two hot queries in /api/scan: 24h cached-result lookup and stale-scan cleanup.

Changes

  • packages/shared/src/db/schema-core.ts — index declaration on the scans table.
  • apps/web/drizzle/0001_scans_repo_status_created_idx.sql — generated migration.
  • apps/web/drizzle/meta/{_journal.json,0001_snapshot.json} — Drizzle metadata.

Migration output

CREATE INDEX "scans_repo_status_created_idx" ON "scans"
  USING btree ("repo_owner","repo_name","status","created_at" DESC NULLS LAST);

Deploy

After merge, run from apps/web:

pnpm db:migrate

Safe to run on a live DB — index creation on a small table is near-instant; Postgres locks briefly (no ACCESS EXCLUSIVE beyond the index build). If the table ever grows past the "briefly" threshold, a separate PR can switch this to CREATE INDEX CONCURRENTLY via .concurrently() on the Drizzle declaration.

Test plan

  • pnpm turbo typecheck passes
  • pnpm turbo build passes
  • pnpm turbo test passes
  • pnpm db:migrate applies cleanly on a dev DB
  • EXPLAIN on the cached-result SELECT and stale-scan UPDATE confirms the new index is used (once the table is large enough for the planner to prefer it over seq scan)

…eated_at DESC)

The /api/scan endpoint runs two queries against `scans` on every scan
submission — the 24h cached-result SELECT and the stale-scan cleanup
UPDATE added in #21 — both filtering by the same four columns in the
same order. Without a supporting index, both do sequential scans; fine
today but a clear hot-path risk as the table grows.

Add a btree index matching the query predicates exactly. Index sort
matches the SELECT's ORDER BY created_at DESC so the planner can use
it without a separate sort.

Closes #22
Copilot AI review requested due to automatic review settings April 24, 2026 17:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a compound btree index to the scans table to speed up the hot-path /api/scan queries that filter by repo owner/name + status and sort by most recent created_at.

Changes:

  • Declare a compound index on scans (repo_owner, repo_name, status, created_at DESC) in the shared Drizzle schema.
  • Add the generated SQL migration to create the index.
  • Update Drizzle migration metadata (journal + snapshot).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
packages/shared/src/db/schema-core.ts Adds the scans_repo_status_created_idx index definition to the Drizzle schema.
apps/web/drizzle/0001_scans_repo_status_created_idx.sql Creates the compound btree index on scans.
apps/web/drizzle/meta/_journal.json Registers the new migration in Drizzle’s journal.
apps/web/drizzle/meta/0001_snapshot.json Updates schema snapshot to include the new index.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@davidstrouk
davidstrouk merged commit 9cae11d into main Apr 24, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add compound index on scans(repo_owner, repo_name, status, created_at)

2 participants