SELECT * FROM users WHERE lower(email) = 'a@x.com'The correct answer is SELECT * FROM users WHERE lower(email) = 'a@x.com'. The index stores email values, not lower(email) values. When you apply a function to the column, the index can no longer match it. Fix it with an expression index: CREATE INDEX ON users (lower(email)). Then the query can use it.
The other queries use the bare email column. A B-tree handles IN, ranges and ordering on the bare column.
Read more