Repository navigation
perf(scans): add compound index on (repo_owner, repo_name, status, created_at DESC) - #23
Merged
Merged
Conversation
…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
There was a problem hiding this comment.
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.
This was referenced Apr 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #22.
Summary
scans (repo_owner, repo_name, status, created_at DESC)./api/scan: 24h cached-result lookup and stale-scan cleanup.Changes
packages/shared/src/db/schema-core.ts— index declaration on thescanstable.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
Deploy
After merge, run from
apps/web: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 CONCURRENTLYvia.concurrently()on the Drizzle declaration.Test plan
pnpm turbo typecheckpassespnpm turbo buildpassespnpm turbo testpassespnpm db:migrateapplies cleanly on a dev DBEXPLAINon 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)