{
  "schema_version": 2,
  "id": "operate/oss_and_stack/stack-with-enterprise/bloom",
  "title": "Probabilistic data structures",
  "url": "https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/bloom/",
  "summary": "Probabilistic data structures",
  "aliases": [
    "/stack/bloom"
  ],
  "tags": [
    "docs",
    "operate",
    "stack"
  ],
  "last_updated": "2026-10-02T14:53:57+01:00",
  "children": [
    {
      "id": "operate/oss_and_stack/stack-with-enterprise/bloom/commands",
      "summary": "Lists probabilistic data structure commands and provides links to the command reference pages.",
      "title": "Probabilistic data structure commands",
      "url": "https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/bloom/commands/"
    },
    {
      "id": "operate/oss_and_stack/stack-with-enterprise/bloom/config",
      "summary": "Probabilistic data structure configuration settings supported by Redis Software and Redis Cloud.",
      "title": "Probabilistic data structure configuration compatibility with Redis Software",
      "url": "https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/bloom/config/"
    }
  ],
  "page_type": "content",
  "content_hash": "3c252a61b94d07839f59bfc31cfef26f771e3c1fd5f2ddf24145cebf1d3c3427",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "A Bloom filter is a probabilistic data structure which provides an\nefficient way to verify that an entry is certainly *not* in a set. This\nmakes it especially ideal when trying to search for items on\nexpensive-to-access resources (such as over a network or disk): If I\nhave a large on-disk database and I want to know if the key *foo* exists\nin it, I can query the Bloom filter first, which tells me with a\ncertainty whether it potentially exists (and then the disk lookup can\ncontinue) or whether it does *not* exist, and in this case I can forego\nthe expensive disk lookup and simply send a negative reply up the stack.\n\nWhile it's possible to use other data structures (such as a hash table)\nto perform this, Bloom filters are also especially useful in that they\noccupy very little space per element, typically counted in the number of\n*bits* (not bytes!). There exists a percentage of false positives\n(which is controllable), but for an initial test of whether a key exists\nin a set, they provide excellent speed and most importantly excellent\nspace efficiency.\n\nBloom filters are used in a wide variety of applications such as ad\nserving - making sure a user doesn't see an ad too often; likewise in\ncontent recommendation systems - ensuring recommendations don't appear\ntoo often, in databases - quickly checking if an entry exists in a\ntable before accessing it on disk, and so on."
    },
    {
      "id": "how-bloom-filters-work",
      "title": "How Bloom filters work",
      "role": "content",
      "text": "Most of the literature on Bloom filter uses highly symbolic and/or\nmathematical descriptions to describe it. If you're mathematically\nchallenged like yours truly, you might find my explanation more useful.\n\nA Bloom filter is an array of many bits. When an element is 'added' to a\nbloom filter, the element is hashed. Then *bit\\[hashval % nbits\\]* is\nset to 1. This looks fairly similar to how buckets in a hash table are\nmapped. To check if an item is present or not, the hash is computed and\nthe filter sees if the corresponding bit is set or not.\n\n![](https://redis.io/docs/latest/images/rs/rebloom-hash1.png)\n\nOf course, this is subject to collisions. If a collision happens, the\nfilter returns a false positive - indicating that the entry is\nindeed found (note that a bloom filter never returns a false\nnegative, that is, claim that something does not exist when it fact it\nis present).\n\nIn order to reduce the risk of collisions, an entry may use more than\none bit: the entry is hashed *bits_per_element (bpe)* times with a\ndifferent seed for each iteration resulting in a different hash value,\nand for each hash value, the corresponding *hash % nbits* bit is set. To\ncheck if an entry exists, the candidate key is also hashed *bpe* times,\nand if any corresponding bit is *unset*, then it can be determined with\ncertainty that the item does *not* exist.\n\nThe actual value of *bpe* is determined at the time the filter is\ncreated. Generally the more bits per element, the lower the likelihood\nof false positives.\n\n![](https://redis.io/docs/latest/images/rs/rebloom-hash3.png)\n\nIn the example above, all three bits would need to be set in order for\nthe filter to return a positive result.\n\nAnother value affecting the accuracy of a Bloom filter is its *fill\nratio*, or how many bits in the filter are actually set. If a filter has\na vast majority of bits set, the likelihood of any specific lookup\nreturning false is decreased, and thus the possibility of the filter\nreturning false positives is increased."
    },
    {
      "id": "scalable-bloom-filters",
      "title": "Scalable Bloom filters",
      "role": "content",
      "text": "Typically Bloom filters must be created with a foreknowledge of how many\nentries they contain. The *bpe* number needs to be fixed, and\nlikewise, the width of the bit array is also fixed.\nUnlike hash tables, Bloom filters cannot be \"rebalanced\" because there\nis no way to know *which* entries are part of the filter (the filter can\nonly determine whether a given entry is *not* present, but does not\nactually store the entries which *are* present).\n\nIn order to allow Bloom filters to 'scale' and be able to accommodate\nmore elements than they've been designed to, they may be stacked. Once a\nsingle Bloom filter reaches capacity, a new one is created atop it.\nTypically the new filter has greater capacity than the previous\none in order to reduce the likelihood of needing to stack yet another\nfilter.\n\nIn a stackable (scalable) Bloom filter, checking for membership now\ninvolves inspecting each layer for presence. Adding new items now\ninvolves checking that it does not exist beforehand, and adding it to\nthe current filter. Hashes still only need to be computed once, however.\n\nWhen creating a Bloom filter - even a scalable one, it's important to\nhave a good idea of how many items it is expected to contain. A filter\nwhose initial layer can only contain a small number of elements will\ndegrade performance significantly because it will take more layers to\nreach a larger capacity."
    },
    {
      "id": "more-info",
      "title": "More info",
      "role": "content",
      "text": "- [Probabilistic data structures quick start](https://redis.io/docs/latest/develop/data-types/probabilistic/bloom-filter)\n- [Probabilistic data structure commands](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/bloom/commands)\n- [Probabilistic data structure configuration](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/bloom/config)\n- [RedisBloom source](https://github.com/RedisBloom/RedisBloom/)"
    }
  ],
  "examples": []
}
