A Bloom filter held 2 million usernames in 2.4 MB at a 1 percent error rate, against 218 MB for a JavaScript Set and 143 MB for a PostgreSQL unique index, with zero false negatives.
A filter sized for 2 million names showed 5.78 percent false positives at 3 million names and 15.76 percent at 4 million, so size for growth and rebuild on a schedule.
A local Postgres probe took only 26 microseconds, so the filter pays off mainly for bot traffic, remote databases or oversized indexes; keep the unique constraint as the final check.