Skip to content

perf(db): index LOWER(email) for the case-insensitive account lookup (#876) - #884

Merged
alex-dembele merged 1 commit into
masterfrom
876-email-lower-index
Oct 2, 2026
Merged

alex-dembele merged 1 commit into
masterfrom
876-email-lower-index

Conversation

@alex-dembele

Copy link
Copy Markdown
Member

Closes #876

Migration 0068_users_email_lower_index: a non-unique index on LOWER(email), the predicate GetByEmail uses since #688. It's not unique on purpose: accounts written before #687 can be case-variant duplicates, and a unique index would fail the migration (and the boot with it) on such a database. docs/MIGRATIONS.md gains the read-only query that lists those duplicates.

Verification

Throwaway Postgres 18, server booted from this branch (AutoMigrate, then the SQL layer):

schema_migrations → 68
idx_users_email_lower → CREATE INDEX idx_users_email_lower ON public.users USING btree (lower(email))
down → DROP INDEX (0 indexes left)
seed 20 000 users + 'Karim@Alpha.test' / 'karim@alpha.test'
up with the duplicate present → DO (index back)   · up again → NOTICE already exists, skipping (idempotent)

EXPLAIN ANALYZE of the exact GetByEmail query, 20 002 rows:

without index: Seq Scan on users … Execution Time: 5.870 ms
with index:    Bitmap Index Scan on idx_users_email_lower  Index Cond: (lower(email) = 'karim@alpha.test'::text)
               Execution Time: 0.107 ms

Duplicate report: karim@alpha.test|2|{Karim@Alpha.test,karim@alpha.test}.

Go gate go build ./... && go vet ./... && go test ./... -race: BUILD_OK · VET_OK · TEST_OK, 80 ok, 0 FAIL. It ran with #882 applied temporarily, because master doesn't build (#881); that commit isn't part of this PR.

Honest remainders

…876)

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
@alex-dembele
alex-dembele merged commit 1196d83 into master Oct 2, 2026
15 of 30 checks passed
@alex-dembele
alex-dembele deleted the 876-email-lower-index branch October 2, 2026 14:30
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.

perf(db): index LOWER(email) — login scans users since #688

1 participant