perf(db): index session and challenge expiry columns

The sliding-30-day session reaper and the passkey-challenge sweep both
filter on expires_at, but neither sessions nor auth_challenges indexed
that column, so the cleanup degraded to a sequential scan on a busy
instance. Every sibling expiry table already indexes its expiry column;
add the two missing indexes via migration 0178.
This commit is contained in:
Marc-André Bombeck committed 2026-06-19 20:52:31 +02:00
1 parent 3e04035de8
commit b3d303217c
2 files changed
+25

No files matched your search

@@ -0,0 +1,19 @@
-- v1.18.7 — expiry indexes for the two tables swept by the session reaper.
--
-- `sessions` (sliding-30-day session expiry) and `auth_challenges` (passkey
-- registration / authentication challenges) are both pruned on `expires_at`,
-- but neither carried an index on that column. On a busy multi-user instance
-- the cleanup degraded to a sequential scan. Every sibling expiry table
-- (`refresh_tokens`, `whoop_oauth_states`, `idempotency_keys`,
-- `withings_oauth_states`, …) already indexes its expiry column; this brings
-- the two stragglers in line. Additive; no data touched.
--
-- Reversibility (down):
-- DROP INDEX IF EXISTS "sessions_expires_at_idx";
-- DROP INDEX IF EXISTS "auth_challenges_expires_at_idx";
-- CreateIndex
CREATE INDEX IF NOT EXISTS "sessions_expires_at_idx" ON "sessions"("expires_at");
-- CreateIndex
CREATE INDEX IF NOT EXISTS "auth_challenges_expires_at_idx" ON "auth_challenges"("expires_at");
+6
View File
@@ -721,6 +721,9 @@ model Session {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
// v1.18.7 — the sliding-30-day session reaper sweeps on `expiresAt`; without
// this index the cleanup degrades to a sequential scan on a busy instance.
@@index([expiresAt])
@@map("sessions")
}
@@ -735,6 +738,9 @@ model AuthChallenge {
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
// v1.18.7 — challenges are swept by expiry; index the column the reaper
// filters on so the cleanup stays index-backed.
@@index([expiresAt])
@@map("auth_challenges")
}