Topic 6.4
Designing a Username Availability API
In one line
A Bloom filter of taken usernames answers "definitely available" instantly for most checks; "maybe taken" goes to the database. Correctness still comes from a unique constraint at registration, and normalisation (case, Unicode NFKC, confusables) must be identical when inserting and checking.
Think of it like this
A sign-up desk with a quick-reference card of names already used. If a name isn't on the card, it's definitely free; if it might be, the clerk checks the official register. And the register itself refuses duplicates at the moment of signing.
Key ideas
- 01
Flow for "is it available?": normalise → Bloom filter: absent → available (fast path) → maybe → database lookup → answer.
- 02
Normalisation: lowercase (case-insensitive usernames), Unicode NFKC normalisation, and possibly confusable mapping (so "раypal" with Cyrillic letters doesn't impersonate "paypal"). The exact same function must run on insert and lookup, or the filter gives false negatives.
- 03
Registration race: two users may both see "available" and submit. The database unique constraint (on the normalised name) decides; the loser gets a friendly "just taken" error. The filter is never used to guarantee uniqueness.
- 04
Updates: add the normalised name to the filter after the insert commits (or via outbox/CDC). A lagging filter says "available" for a just-taken name; that's safe because registration still hits the constraint, and the availability UI may briefly be optimistic.
- 05
Deletions (account closures freeing names) leave stale bits → "maybe taken" → database says free: a false positive, harmless.
Code & diagrams
static String normalizeUsername(String raw) {
String nfkc = Normalizer.normalize(raw.strip(), Normalizer.Form.NFKC);
String lower = nfkc.toLowerCase(Locale.ROOT);
return confusables.skeleton(lower); // e.g. ICU SpoofChecker-based mapping
}
// The SAME function feeds bloom.add(...) on registration and bloom.mightContain(...) on checks,
// and the database UNIQUE index is on the normalised column.Interview problem
The problem
Username availability API for 100M users
Design a username availability API for 100 million registered usernames. Discuss the Bloom filter, Redis, the database, registration races, case and Unicode normalisation, and the source of truth.
Explain it without notes
Why is the Bloom filter never used to guarantee a username is unique?
Practice
List three normalisation mismatches that would cause false negatives, and how to prevent them.
Trade-offs
- ↔
Fast availability checks at the cost of maintaining a filter; correctness remains in the database.
Done when you can
I can design a username availability API with correct normalisation and race handling.