Scalar (int8) quantization·6 min
Why quantize
0 / 1
Vectors are the memory hog. A corpus of 100k × 128 float32 = 51 MB; a billion vectors = terabytes. Qdrant's scalar quantization maps each float32 dimension to a signed int8 (4x smaller, faster integer distance), then rescores the top candidates with the original float32 vectors to recover accuracy.
The mapping
Signed int8 codec
bucket = round( (f - offset) / alpha ) in [0, 255]
i8 = bucket - 128 in [-128, 127]
f ~= alpha * (i8 + 128) + offset
[offset, offset + 255*alpha] = the value range, taken at a
quantile (~0.99) to clip outliers.
Worked example, value range [-0.5, 0.5]: offset = -0.5, alpha = 1.0/255 ≈ 0.003922.
f = 0.0→ bucketround((0 + 0.5)/0.003922) = round(127.5) = 128→i8 = 0. Recover:0.003922·128 - 0.5 ≈ 0.0. ✓f = -0.5→ bucket0→i8 = -128.f = 0.5→ bucket255→i8 = 127.
Every code lands in [-128, 127]; the value 128 never appears.
Signed int8, end to end
We use signed int8 [-128, 127] everywhere — it matches Int8Array and Qdrant's int8 framing. Qdrant's articles show both signed and unsigned variants; we pick signed and never mix them, so the fixture codes are signed integers.