CloudBitmaps

Flavors · one engine, pluggable codecs

Pick the codec that matches your ids.

@cloudbitmaps/core is codec-agnostic. The cache over immutable generations, the load-and-publish write path, chunk-skipping intersection, generation GC, erasure-by-rewrite, encryption, retention and the four storage drivers live there and do not change. A flavor decides one thing — how a chunk of ids is represented on the wire and at rest.

How Roaring works → Zero-setup quickstart

Choose on the shape of your id space, not on a benchmark.

Choose one

One of these ships. The other two are on this page so the shape of the plan is visible — there is no page for a package you cannot install, and a row becomes a link the day it publishes.

FlavorsScrolls sideways on narrow screens
Flavor Status Take it when Cost of choosing it
@cloudbitmaps/roaring Adaptive containers — array, bitset, run Shipped · v0.10.0 Ids are sparse or clustered and adaptive containers do real compression work. The default: if you are moving off Redis sets, start here. A native dependency and its platform matrix.
@cloudbitmaps/bitset One bit per id — no containers, no branches Not planned Nothing, and that is a measured result rather than an opinion. Above about 6% density a Roaring chunk is an uncompressed bitset, so there is no size to win: on the shape built to favour a plain bitset it comes out 2% ahead, and Roaring wins the other three by 543×, 63× and 1.88×. It would be a plausible wrong turn — picked for dense ids, where Roaring has already become the same bitset.
@cloudbitmaps/soaring A separate algorithm, unproven Research Under research, with nothing to install. It ships only if the algorithm proves out against roaring on real workloads — and if it does not, this row goes away. —

Adding a flavor is one row here and one figure on its own page. Nothing else on the site changes, because nothing else depends on the codec.

Where the choice does not matter

Every flavor is a codec plugged into the same store. Swapping one is an import change and a re-load of your segments — the drivers, the forward-only pointer protocol, the cache and the container format around the payload all stay put.

Cost

$82.40 per million cold intersects of two segments sharing 100 of 1,999 chunks, from requests measured on S3, and $11.20 per million loads written and published, pointer included — store.load() is expected at about twice that — against $346/mo standing for a Redis-HA node. Billed by the request either way — a codec changes bytes, not the pricing model.

The moat

100 of 2,000 chunks fetched when intersecting two 2,000,000-id segments — the shared keys only. Key alignment happens above the codec, so it survives every flavor. Step through it.

When to walk away

No flavor fixes this. Sub-millisecond p99 on a working set that fits a bounded cache is a different machine; a membership check that misses the cache costs one ranged GET against object storage, where a RAM store costs a memory read. Use Redis.

The API, whichever you pick

has · count · iterate, and the full set algebra — intersect, union, andNot — plus *Into variants that publish the result as a new generation of a destination segment instead of returning it. Data arrives the one way whichever you pick — store.load, one immutable object then a forward-only pointer move. A flavor is a CodecInterface implementation underneath four drivers and two tiers, and changes none of these signatures.

Start with roaring.

It is the one that ships, and it is the right default unless you already know your ids are dense. The memory drivers need no configuration, so the quickstart runs before you decide anything about storage.

Apache-2.0 · v0.10.0 · zero-dependency core · 4 storage drivers

InstallA codec and a storage
npm i @cloudbitmaps/roaring @cloudbitmaps/s3

# the memory and local drivers need nothing else
# for a real backend, add its package:
# @cloudbitmaps/s3 · @cloudbitmaps/gcs · @cloudbitmaps/azure-blob