Skip to content

Probabilistic Data Structures Patterns

Probabilistic structures trade exactness for massive space savings. They give approximate answers with bounded error probabilities — perfect for large-scale systems where exact answers are too expensive.

What: Set membership test. “Definitely not in set” or “probably in set.”

How: k hash functions, m-bit array. Insert: set bits at h1(x), h2(x), …, hk(x). Query: check all k bits.

class BloomFilter:
def __init__(self, size, num_hashes):
self.bits = [False] * size
self.size = size
self.num_hashes = num_hashes
def _hashes(self, item):
# Double hashing: h(i) = h1 + i*h2
h1 = hash(item) % self.size
h2 = hash(repr(item)) % self.size
return [(h1 + i * h2) % self.size for i in range(self.num_hashes)]
def add(self, item):
for h in self._hashes(item):
self.bits[h] = True
def might_contain(self, item):
return all(self.bits[h] for h in self._hashes(item))

False positive rate: (1 - e^(-kn/m))^k where n = items inserted.

Optimal k: k = (m/n) * ln(2)

Use cases: Spell checkers, cache lookups, database query optimization, network routers.

What: Frequency estimation. Answers “how many times has X appeared?” with bounded overcount.

How: d hash functions, d × w counter matrix. Increment all d counters on insert. Query returns minimum across d counters.

Error bound: Overestimates by at most ε*N with probability 1-δ, where w = ⌈e/ε⌉, d = ⌈ln(1/δ)⌉.

Use cases: Network traffic monitoring, trending topics, heavy hitters detection.

What: Cardinality estimation (count distinct). Estimates unique elements using O(log log n) space.

How: Hash each element, count leading zeros. The maximum number of leading zeros estimates log2 of cardinality.

Practical accuracy: ~2% error with 1.5KB of memory for billions of unique elements.

Use cases: Unique visitor counting, database APPROX_COUNT_DISTINCT, Redis PFCOUNT.

What: Probabilistic alternative to balanced BSTs. Expected O(log n) search/insert/delete.

How: Multi-level linked list. Each element is promoted to the next level with probability 1/2. Search starts at top level, drops down when the next element is too large.

Advantages over BSTs: Simpler to implement, naturally lock-free, used in Redis sorted sets and LevelDB.

CompanyFocusDifficulty
GoogleBloom filters in BigTable, HyperLogLogMedium-Hard
NetflixStreaming cardinality estimationMedium
DatabricksApproximate query processingMedium-Hard
AmazonDynamoDB bloom filtersMedium
StripeRate limiting with count-min sketchMedium
StructureSpaceFalse PositivesDeletionsUse
Hash SetO(n)NoneYesExact membership
Bloom FilterO(1) per elementYes (~1%)No*Approximate membership
Counting BloomO(1) per elementYesYesMembership + delete
Count-Min SketchO(1/ε * log(1/δ))OvercountsWith negative countsFrequency estimation
HyperLogLogO(log log n)±2%NoCardinality

*Cuckoo filters support deletion and have better space efficiency for low false-positive rates.