What Are Bloom Filters? Learn How They Function

Ever wondered how massive platforms like Meta, Google, or Twitter know instantly if your username is taken, even with billions of users?
Do they just check in the DB or cache for it?
What’s the Problem with Simply Checking?
Searching for an element in a big dataset isn’t cheap:
Naive: Loop through every entry — O(n) time. Way too slow!
Database Indexes: Sorted, so O(log n). Better, but every disk access costs time.
Hash Sets: In-memory, O(1) lookup — but the catch? For huge numbers of items, your memory bill explodes.
So how do you check for existence — fast and cheap — when your dataset is gigantic?
That’s where Bloom Filters come in.
How does a Bloom Filter help?
A Bloom filter is a probabilistic data structure that helps us quickly check if a value is present in a dataset using very little memory.
It doesn’t always give a perfectly correct answer, but it’s extremely efficient for large-scale applications.
Okay, but how?
At its core, a Bloom filter is just:
A bit array of fixed length m.
A set of hash functions k that map inputs to positions in that array.
When you insert an element, you run it through each hash function, and set the corresponding bits to 1.
When you query an element, you check if all of its hash positions are 1.
If any bit is 0 → the element is definitely not in the set.
If all bits are 1 → the element is probably in the set.
Why does this work?
Here’s the golden rule:
If even one of the required bits is 0, there’s no way the element was ever inserted.
But if all bits are 1, a Bloom filter may say “element exists” when it actually doesn’t. This happens because multiple elements may hash to the same positions, filling the same bits.
Let's try to understand this with an example consider we have a bit array of size 10
Bit array : 0 0 0 0 0 0 0 0 0 0
- Step 1: Insert "cat"
Hash1 → position 3
Hash2 → position 7
Set bits [3, 7] to 1.
Bit array: 0 0 0 1 0 0 0 1 0 0
- Step 2: Insert "dog"
Hash1 → position 4
Hash2 → position 7 Set bits [4, 7].
Bit array: 0 0 0 1 1 0 0 1 0 0
- Step 3: Query "cat"
Hash1 → 3 → bit = 1
Hash2 → 7 → bit = 1 ✅ Both bits set → "cat" is present.
- Step 4: Query "lion"
Hash1 → 2 → bit = 0
Hash2 → 5 → bit = 0 ❌ At least one bit is 0 → "lion" is definitely not present.
- Step 5: Query "bat"
Hash1 → 3
Hash2 → 4 Both 3 and 4 are already set (due to "cat" and "dog"). 👉 Bloom filter says "bat" is present.
But… we never inserted "bat". That’s a false positive.
What does this mean?
Bloom filters can have false positives: they might say an element is present even if it was never inserted.
But Bloom filters will never have false negatives: if an element was inserted, it will always be reported as present.
This is the core trade-off:
We accept a small chance of false positives in exchange for massive memory savings and speed.
Why False Negatives Don’t Happen
If an element was inserted, its bits were set. Those bits never get unset. So querying that same element will always find them.
False positives happen. False negatives don’t. Period.
Downsides
Cannot delete items in regular Bloom filters. (Variations like Counting Bloom Filters fix this.)
If you insert too many elements, the filter gets saturated and false positives rise.
We can solve this by rebuilding filters periodically or using scalable variations for systems where datasets grow and shrink.
Bloom Filters at Scale: Real-World Usage Big platforms (Meta, Google, Twitter) use Bloom filters for pre-filtering requests like username lookup:
User submits a username.
Bloom filter checks: If not present, instantly say “available,” no cache or DB needed.
If the filter says “might be present,” check cache, then DB for confirmation.
Why? 99% of the "nope, already taken" answers are delivered instantly, saving millions of database calls.
Subscribe to my newsletter
Read articles from Sahil Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
