Cassandra Bloom Filters
A Bloom filter is a space-efficient data structure that answers one question very quickly: "Is this partition key definitely NOT in this SSTable?" If the answer is yes, Cassandra skips the SSTable entirely — saving a disk read. If the answer is maybe, Cassandra checks the SSTable. Bloom filters are stored in memory and make Cassandra's read path dramatically faster on tables with many SSTables.
The "Guest List" Analogy
Imagine a nightclub bouncer with a rough list of guest names. The list might say "John Smith is NOT on the list" with certainty, but if it says "John Smith might be on the list," the bouncer still checks the actual guest book to confirm. A Bloom filter works exactly like that rough list — it gives definite NO answers quickly and probabilistic YES answers that still require verification.
SSTable Bloom Filter:
Query: "Is partition key 'order-uuid-X' in SSTable-4?"
→ Bloom filter says: "Definitely NOT here"
→ Skip SSTable-4 entirely ✓ (zero disk I/O)
Query: "Is partition key 'order-uuid-Y' in SSTable-4?"
→ Bloom filter says: "Maybe here"
→ Check SSTable-4's partition index → found (true positive) ✓
OR not found (false positive) ⚠
How a Bloom Filter Works
A Bloom filter is a bit array of N bits, all initialized to zero. When you add a key, you hash it with multiple hash functions and set the corresponding bits to 1. To check if a key is present, you hash it the same way and check whether all those bits are 1. If any bit is 0, the key is definitely absent. If all bits are 1, the key is probably present (but could be a false positive).
Bit array (10 bits): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] Add key "order-A" (3 hash functions → positions 2, 5, 8): [0, 0, 1, 0, 0, 1, 0, 0, 1, 0] Add key "order-B" (hash → positions 1, 4, 7): [0, 1, 1, 0, 1, 1, 0, 1, 1, 0] Check "order-A": positions 2, 5, 8 → all 1 → MAYBE ✓ Check "order-Z": positions 0, 3, 6 → bits are 0 → DEFINITELY NOT ✓ Check "order-Q": positions 1, 4, 8 → all 1 → MAYBE (false positive ⚠)
False Positives in Bloom Filters
A false positive occurs when the Bloom filter says "maybe" for a key that is not actually in the SSTable. Cassandra then reads the SSTable's partition index — an unnecessary disk read. False positives waste I/O but never produce incorrect data. The false positive rate is configurable.
False Positive Rate (FPR) trade-off:
Low FPR (e.g., 0.01 = 1%): Very accurate → fewer disk reads
Larger Bloom filter → more memory
High FPR (e.g., 0.10 = 10%): More false positives → more disk reads
Smaller Bloom filter → less memory
Configuring the Bloom Filter False Positive Rate
Each table has its own Bloom filter setting. The default false positive chance is 0.1 (10%). Reduce it for read-heavy tables to decrease unnecessary disk reads at the cost of more memory.
-- More accurate Bloom filter (1% false positive rate): CREATE TABLE hot_orders ( order_id UUID PRIMARY KEY, total DECIMAL ) WITH bloom_filter_fp_chance = 0.01; -- Less accurate but smaller (15% false positive rate): CREATE TABLE cold_archive ( record_id UUID PRIMARY KEY, data TEXT ) WITH bloom_filter_fp_chance = 0.15; -- Alter existing table: ALTER TABLE hot_orders WITH bloom_filter_fp_chance = 0.01;
Bloom Filter Memory Usage
Bloom filter memory scales with the number of partition keys in the SSTable and the configured false positive rate. More partitions or a lower FPR means a larger filter.
Approximate Bloom filter size formula: size ≈ (-n × ln(p)) / (ln(2)²) Where: n = number of partition keys in the SSTable p = desired false positive rate Examples (n = 1,000,000 partitions): FPR 0.10 (10%): ~600 KB FPR 0.01 (1%): ~1.2 MB FPR 0.001 (0.1%): ~1.8 MB
Bloom Filter Storage
Each SSTable has its own Bloom filter stored in a Filter.db file alongside the SSTable. When Cassandra starts, it loads all Bloom filters into memory (off-heap). Bloom filters from newly created SSTables are built during the flush process.
SSTable files: mb-1-big-Data.db ← row data mb-1-big-Filter.db ← Bloom filter (loaded into off-heap RAM) mb-1-big-Index.db ← partition index ...
Checking Bloom Filter Effectiveness
nodetool gives you metrics on Bloom filter hit and false positive rates per table, helping you decide whether to lower the false positive chance.
nodetool tablestats ecommerce Table: orders_by_customer Bloom filter false positives: 234 Bloom filter false ratio: 0.0023 Bloom filter space used: 1.2 MB Bloom filter off-heap memory used: 1.2 MB
A false ratio above 0.01 (1%) on a read-heavy table is a signal to lower bloom_filter_fp_chance.
Compaction and Bloom Filters
When compaction merges SSTables, it builds a new Bloom filter for the merged SSTable automatically. The old Bloom filters (from the merged SSTables) are discarded from memory. This keeps the in-memory Bloom filter footprint proportional to the current SSTable count rather than accumulating over time.
When to Tune Bloom Filters
Scenario Recommendation ────────────────────────────────────────────────────────────── Read-heavy table with many SSTables Lower FPR to 0.01 or 0.001 Write-heavy table, rarely read Keep default 0.1 to save memory Time-series data (TWCS compaction) Default usually fine; few SSTables Large archive table, cold reads OK Higher FPR (0.2) to save memory Memory constrained cluster Raise FPR cluster-wide carefully
Summary
Bloom filters are in-memory probabilistic structures that allow Cassandra to skip SSTables that definitely do not contain a requested partition key, saving disk I/O. They produce no false negatives but may produce false positives, causing an occasional unnecessary SSTable check. The bloom_filter_fp_chance table property controls the trade-off between memory usage and read efficiency. Lower the false positive rate on read-intensive tables to improve query performance, and monitor false ratios with nodetool to know when tuning is needed.
