The 30 second answer
If I wrap an indexed column in a function in the WHERE clause, like lowercasing an email, a normal index on that column cannot be used and the database scans the table. I either rewrite the condition so the column stays bare, for example using a date range instead of extracting the date, or I create an expression index that matches the function exactly.
An index on email can't serve WHERE lower(email) = ?. Either rewrite the condition or create an index on the expression.
CREATE INDEX ON users (lower(email));
-- or rewrite: WHERE created_at >= '2026-01-01' AND created_at < '2026-01-02' instead of date(created_at) = ...