HeatherDB

Search documentation

Loading the documentation index…

Download
HeatherDB documentation
DocumentationReference

Capacity reference

The measured limits of superposition, and what to do at each wall.

Every number here is measured, not derived. Recall percentages are the fraction of stored items a read returns correctly. Unless a row says otherwise, the figures come from numpy models of the same arithmetic the engine runs; the live-engine walls are one notch tighter (see Live engine vs. numpy).

The escape from a capacity wall is sharding into more collections, not raising the dimension. Dimension buys a square-root; sharding buys a linear factor and is not immutable.

Per-pool capacity

How many patterns superpose into one location before per-read recall degrades.

DItems per pool at ≥90% recall
51232
102432
204864

The rule of thumb is D/32, which is what tau_overload defaults to (max(d/32, 8)): a saturating location splits as it reaches the wall rather than well past it.

The failure mode is a read that blends several stored patterns into a plausible-looking vector matching none of them. Fidelity is the detector.

Schema capacity

Role–filler slots recoverable from one bundle. The bound is √(D/32), not D/32 — each slot costs a bind, and crosstalk grows with the number of slots rather than the number of items.

At D = 1024:

SlotsRecall
2100%
3100%
494%
622%
≥80%

Raising D restores it. At 8 slots:

DRecall
10240%
204815%
409696%
8192100%

Doubling D roughly doubles the recoverable slot count, so an 8-slot schema wants D ≥ 4096 and a 16-slot schema is a re-design, not a bigger dimension.

Sharding

Same total item count N, one collection versus shards holding 16 items each.

Total NUnsharded recallSharded at pool 16
12862%100%
5127%100%
20480%100%

Sharding is the only lever that holds recall flat as N grows. Route across shards with POST /db/{db}/compose/read, which weights each collection by how well the query matches it.

Multi-hop recall

Per-hop recall multiplies. A chain of h hops recalls at roughly r^h, where r is the single-hop recall at that pool size.

Pool N1 hop3 hops6 hops
16100%100%100%
12863%17%—

A traversal of any depth wants pool sizes at or under 16. Deep chains are a sharding problem before they are a dimension problem.

Live engine vs. numpy

The engine's walls sit one notch tighter than the pure arithmetic, because a read also pays for competitive placement, activation over k locations, and a finite softmax temperature.

At D = 1024, ≥90% recall:

βEngine holds to Nnumpy holds to N
5 (default)1632
30exact-nearest-neighbour ceiling—

β is a softmax temperature and costs the same to evaluate at any value, so a soft β buys nothing. β = 30 is also the clamp floor for role cleanup (MIN_CLEANUP_BETA). Raise beta in db.toml, or read with attention/mdl and let the engine pick β per query from the codebook's geometry.

Location saturation

A location saturates at roughly d/32 writes, which is the tau_overload default. Watch it with GET …/collections/{name}/stats:

stats.max_write_count vs. tau_overloadState
< 0.5 ×Healthy. Locations are well below the wall
0.5–1.0 ×Approaching. Splits are imminent for the hottest locations
≈ 1.0 × and num_locations climbingSplitting normally. Expected steady state
> 1.0 × and num_locations flatSplits are not firing. Check competitive = false, or an mdl_gate that finds the traffic coherent

avg_write_count far below max_write_count means the load is concentrated on a few locations — a skewed key distribution, not a capacity problem. Reads against the cold locations are fine; reads against the hot one blend.

Choosing under a wall

SymptomLever
Reads blend several stored patternsRaise beta, or use attention/mdl; lower k
Recall falls as the collection growsShard. More collections, not more dimensions
A schema loses slots as you add fieldsRaise D (√ scaling), or split the record across collections
A traversal loses the trail after two hopsShrink pools to ≤ 16
max_write_count past tau_overload, locations flatLower tau_overload, or turn off mdl_gate
Location count grows without boundPOST …/compress to merge to the MDL minimum