Bloom Filters Explained: The Space-Saving Magic Trick
A tiny structure that tells you an item is definitely not in a set using barely any memory. Bloom filters explained — bit arrays, hash functions, false positives, and why Cassandra and caches use them.
🟠Fundamentals · Senior → 🔴 super-senior deep dive
Here's a magic trick real systems use every day: a tiny data structure that can tell you "this item is definitely not here" using a fraction of the memory it would take to store the items themselves. It's called a Bloom filter, and it quietly powers databases, caches, and web browsers. It sounds like cheating — and understanding how it cheats (and what it gives up) is a beautiful senior-level interview topic. Let's build the intuition step by step.
The problem it solves
Imagine you have a billion URLs you've already crawled, and before crawling a new one you want to check "seen it?" Storing a billion full URLs in memory is enormous. But often you don't need the exact set — you just need a fast, cheap way to skip the ones you've definitely seen, and only do the expensive real check for the rest. That's exactly what a Bloom filter gives you.
How it works
🔴 A Bloom filter is just a bit array (all zeros to start) plus a few hash functions. Two operations:
- Add an item: run it through, say, 3 hash functions to get 3 positions in the array, and set those 3 bits to 1.
- Check an item: hash it the same way to get its 3 positions. If any of those bits is 0, the item was definitely never added (adding it would have set them). If all 3 are 1, it's probably present.
That's the whole thing. The "definitely no" is certain because a missing item can't have set bits it never touched. The "probably yes" is uncertain because a different item's hashes might have set exactly the same bits — a collision.
The one-way guarantee (this is the key)
🔴 The asymmetry is the entire point:
- No false negatives: if the filter says "not present," it is truly not present — 100% reliable. This is what makes it safe to use as a skip check.
- Possible false positives: if it says "present," it's usually right but occasionally wrong. So a "yes" means "go do the real, expensive lookup to confirm."
You tune the false-positive rate by choosing the array size and number of hash functions: bigger array + well-chosen hash count = fewer collisions = fewer false positives, at the cost of a bit more memory. Even at ~1% false positives, a Bloom filter is a fraction of the size of the real data.
Where it's used (this is why it matters)
| System | Uses a Bloom filter to… |
|---|---|
| Cassandra, HBase, RocksDB (LSM-trees) | Skip reading SSTable files that can't contain the key — huge read speedup |
| Caches / CDNs | Avoid a slow DB lookup for keys that were never stored |
| Web crawlers | Quickly skip already-seen URLs |
| Browsers / databases | Fast "is this malicious URL / does this key exist?" pre-check |
The pattern is always the same: use the filter as a cheap first gate. "Definitely no" → skip the expensive work entirely. "Probably yes" → do the real lookup. Since most checks in these systems are misses, the filter saves enormous amounts of I/O.
The catch: you can't easily delete
🔴 One senior nuance. You can't simply remove an item by clearing its bits — those bits might be shared with other items, so clearing them would create false negatives (breaking the core guarantee). Standard Bloom filters are add-only. If you need deletion, you use a Counting Bloom filter (each slot is a small counter you increment/decrement instead of a single bit). Knowing this limitation and its fix is exactly the depth interviewers probe for.
The interview-ready summary
"A Bloom filter is a space-efficient probabilistic structure that tells me if an item is definitely not in a set or probably in it — a bit array plus a few hash functions. It has no false negatives but some false positives, so I use it as a cheap gate: a 'no' lets me skip expensive work, a 'yes' means do the real lookup. It's why LSM-tree databases like Cassandra avoid touching SSTables that can't hold a key. It's add-only, so for deletes I'd use a counting Bloom filter." Concise, and it shows you know both the mechanism and the trade-off."
What to read next
- LSM-Tree vs B-Tree — the storage engines that rely on Bloom filters
- Caching Strategies — avoiding lookups for keys that don't exist
- Consistent Hashing — another elegant structure behind distributed data
- ← The complete System Design guide (hub)