redis-roaring [](https://coveralls.io/github/aviggiano/redis-roaring?branch=master) [](https://github.com/aviggiano/redis-roaring/actions/workflows/ci.yml) [](https://redisroaring.com)

July 1, 2026 ยท View on GitHub

Roaring Bitmaps for Redis

Intro

This project uses the CRoaring library to implement roaring bitmap commands for Redis. These commands can have the same performance as redis' native bitmaps for O(1) operations and be up to 8x faster for O(N) calls, according to microbenchmarks, while consuming less memory than their uncompressed counterparts (benchmark pending).

Pull requests are welcome.

Dependencies

  • CRoaring (bitmap compression library used by this redis module)
  • cmake (build tools needed for compiling the source code)
  • redis (server needed for integration tests)
  • hiredis (redis client library needed for performance tests)

Redis Version Compatibility

This module is intended to support Redis 6.2 and 7.0 (the versions we test in CI).

  • Redis 7.4+: Full feature support including custom ACL categories, command ACL categories, and command introspection
  • Redis 7.2 - 7.3: Command introspection and command ACL categories supported
  • Redis 7.0 - 7.1: Command introspection (COMMAND INFO, COMMAND DOCS) supported
  • Redis 6.2: Core roaring bitmap functionality supported

The module automatically detects the Redis version at runtime and adjusts its behavior accordingly:

  • Command metadata (via RedisModule_SetCommandInfo) is only registered on Redis 7.0+
  • Command ACL categories (via RedisModule_SetCommandACLCategories) are only set on Redis 7.2+
  • Custom ACL categories (via RedisModule_AddACLCategory) are only registered on Redis 7.4+

All core roaring bitmap commands work on Redis 6.0+.

Getting started

$ git clone https://github.com/aviggiano/redis-roaring.git
$ cd redis-roaring/
$ configure.sh
$ cd dist 
$ ./redis-server ./redis.conf  

then you can open another terminal and use ./redis-cli to connect to the redis server

Docker

It is also possible to run this project as a docker container.

docker run -p 6379:6379 aviggiano/redis-roaring:latest

Tests

Run the test.sh script for unit tests, integration tests and performance tests. The performance tests can take a while, since they run on a real dataset of integer values.

Migrating to Redis native bitmaps

After redis/redis#15296, core Redis supports native Roaring-backed bitmaps. We recommend migrating redis-roaring keys to core Redis for long-term upstream support, standard Redis persistence and replication behavior, and simpler operational tooling.

The standalone tools/redis-bitmap-migrate.py utility migrates R.* and R64.* redis-roaring keys into Redis native bitmap values through public Redis and redis-roaring commands. It streams integer ranges from the source, writes native bitmap values on the target, validates temporary keys, and records a durable JSON manifest. It does not depend on Redis core internals or redis-roaring private payload layouts.

By default the tool performs a dry run:

python3 tools/redis-bitmap-migrate.py \
  --source-host 127.0.0.1 --source-port 6379 \
  --target-host 127.0.0.1 --target-port 6380 \
  --manifest redis-bitmap-migrate-manifest.json

To write destination keys, run a final pass while source writes are frozen and acknowledge that with --apply --assume-frozen.

python3 tools/redis-bitmap-migrate.py \
  --source-host 127.0.0.1 --source-port 6379 \
  --target-host 127.0.0.1 --target-port 6380 \
  --manifest redis-bitmap-migrate-manifest.json \
  --apply --assume-frozen

Run the migrator contract tests with:

python3 -m py_compile tools/redis-bitmap-migrate.py tests/integration/redis-bitmap-migrate.py
python3 tests/integration/redis-bitmap-migrate.py

The default test run uses fake RESP servers to verify the public-command contract. Real Redis-to-native integration tests are enabled when REDIS_NATIVE_SERVER, REDIS_ROARING_SERVER, and REDIS_ROARING_MODULE point to built binaries.

Fuzzing

redis-roaring includes fuzz testing using libFuzzer with AddressSanitizer and UndefinedBehaviorSanitizer. Five fuzz targets cover 32-bit operations, 64-bit operations, complex bitwise operations, data parsing, and BITOP key-discovery metadata. Fuzzing runs automatically on every push to master.

Build and run fuzzers locally with ./scripts/build_fuzzers.sh (requires Clang). Run individual fuzzers with ./scripts/run_fuzzer.sh <fuzzer_name> <duration> or all fuzzers with ./scripts/run_all_fuzzers.sh.

See docs/fuzzing.md for complete documentation.

API

๐Ÿ“– Complete Documentation: For detailed command documentation including syntax, parameters, examples, and usage notes, see docs/commands/index.md

The following operations are supported

  • R.SETBIT (same as SETBIT)
  • R.GETBIT (same as GETBIT)
  • R.BITOP (same as BITOP)
  • R.BITCOUNT (same as BITCOUNT without start and end parameters)
  • R.BITPOS (same as BITPOS without start and end parameters)
  • R.SETINTARRAY (create a roaring bitmap from an integer array)
  • R.GETINTARRAY (get an integer array from a roaring bitmap)
  • R.SETBITARRAY (create a roaring bitmap from a bit array string)
  • R.GETBITARRAY (get a bit array string from a roaring bitmap)

Additional commands

  • R.APPENDINTARRAY (append integers to a roaring bitmap)
  • R.RANGEINTARRAY (get an integer array from a roaring bitmap with start and end, so can implements paging)
  • R.SETRANGE (set or append integer range to a roaring bitmap)
  • R.SETFULL (fill up a roaring bitmap in integer)
  • R.STAT (get statistical information of a roaring bitmap)
  • R.OPTIMIZE (optimize a roaring bitmap)
  • R.MIN (get minimal integer from a roaring bitmap, if key is not exists or bitmap is empty, return -1)
  • R.MAX (get maximal integer from a roaring bitmap, if key is not exists or bitmap is empty, return -1)
  • R.DIFF (get difference between two bitmaps)

64-bit bitmap commands (for handling values beyond 32-bit range)

  • R64.SETBIT (64-bit version of SETBIT)
  • R64.GETBIT (64-bit version of GETBIT)
  • R64.SETINTARRAY (create a 64-bit roaring bitmap from an integer array)
  • R64.GETINTARRAY (get an integer array from a 64-bit roaring bitmap)
  • R64.RANGEINTARRAY (get an integer array from a 64-bit roaring bitmap with start and end)
  • R64.APPENDINTARRAY (append integers to a 64-bit roaring bitmap)
  • R64.DIFF (get difference between two 64-bit bitmaps)
  • R64.SETFULL (fill up a 64-bit roaring bitmap)

Missing commands:

API Example

$ redis-cli
# create a roaring bitmap with numbers from 1 to 99
127.0.0.1:6379> R.SETRANGE test 1 100

# get all the numbers as an integer array
127.0.0.1:6379> R.GETINTARRAY test

# fill up the roaring bitmap 
# because you need $2^{32}$*4 bytes memory and a very long time
127.0.0.1:6379> R.SETFULL full

# use `R.RANGEINTARRAY` to get numbers from 100 to 1000 
127.0.0.1:6379> R.RANGEINTARRAY full 100 1000

# append numbers to an existing roaring bitmap
127.0.0.1:6379> R.APPENDINTARRAY test 111 222 3333 456 999999999 9999990

Performance

Tested using CRoaring's census1881 dataset. Performance tests are run automatically on every push to master branch.

OPTIME/OP (us)ST.DEV. (us)
R.SETBIT51.1914.06
R64.SETBIT52.0115.01
SETBIT50.5914.06
R.GETBIT50.717.76
R64.GETBIT50.867.81
GETBIT49.107.59
R.BITCOUNT47.680.04
R64.BITCOUNT46.130.07
BITCOUNT59.580.11
R.BITPOS45.190.04
R64.BITPOS45.610.04
BITPOS51.930.21
R.BITOP NOT94.061.26
R64.BITOP NOT103.551.21
BITOP NOT214.811.19
R.BITOP AND54.180.22
R64.BITOP AND54.590.18
BITOP AND268.803.76
R.BITOP OR63.981.19
R64.BITOP OR65.840.73
BITOP OR423.986.97
R.BITOP XOR64.671.11
R64.BITOP XOR64.770.69
BITOP XOR382.636.05
R.BITOP ANDOR52.740.13
R64.BITOP ANDOR54.600.18
BITOP ANDOR397.346.38
R.BITOP ONE62.360.67
R64.BITOP ONE70.290.91
BITOP ONE427.306.98
R.MIN46.790.05
R64.MIN45.770.02
MIN46.140.17
R.MAX45.570.02
R64.MAX46.580.04
MAX45.940.02