Skip to content

Commit 96b2959

Browse files
authored
perf(database): index PersonalAccessToken.userId so token lookups stop seq-scanning (#4588)
## Summary The two personal-access-token lookups by `userId` (one also filtering `revokedAt is null`, the other also filtering `name`) had no index on `userId`, so each did a full sequential scan of the `PersonalAccessToken` table to return a single row. `userId` is also an unindexed foreign key. ## Fix Add a single `@@index([userId])`. A user owns only a handful of PATs, so once `userId` is indexed each lookup touches a few rows and the residual `revokedAt` / `name` filter is trivial. Both query shapes lead with `userId =`, so one index serves both and a composite would only add write cost. The migration uses `CREATE INDEX CONCURRENTLY IF NOT EXISTS`, which is online-safe under write load and reversible by dropping the index. Verified with a seeded local EXPLAIN: both queries go from a full sequential scan to an index scan on the new index.
1 parent db0ca9e commit 96b2959

3 files changed

Lines changed: 9 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: improvement
4+
---
5+
6+
Speed up personal access token lookups by indexing them on their owner
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CREATE INDEX CONCURRENTLY IF NOT EXISTS "PersonalAccessToken_userId_idx" ON "public"."PersonalAccessToken"("userId");

internal-packages/database/prisma/schema.prisma

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ model PersonalAccessToken {
155155
updatedAt DateTime @updatedAt
156156
157157
authorizationCodes AuthorizationCode[]
158+
159+
@@index([userId])
158160
}
159161

160162
enum OrganizationAccessTokenType {

0 commit comments

Comments
 (0)