altor-vec vs hnswlib

altor-vec vs hnswlib — Pure JS vs WASM

A fair comparison between altor-vec and hnswlib starts with deployment boundaries, not hype. altor-vec is built for browser-native HNSW retrieval with almost no operational overhead. hnswlib assumes a server, service, or native runtime and gives you the controls that environment usually needs. If your product team confuses those boundaries, it will either overbuild for a simple public search surface or underbuild for a private, business-critical retrieval workflow.

Install altor-vec: npm install altor-vec

Feature comparison table

Capabilityaltor-vechnswlib
EnvironmentBrowser / JS integrationPython / C++ native
AlgorithmHNSWHNSW
Install shapenpm + WASMNative bindings
Best forWeb appsBackend services / notebooks
Incremental addYesYes
Operational boundaryFrontend-ownedBackend-owned

The table shows why these tools often appear in the same shortlist even though they are not direct drop-in substitutes. altor-vec is strongest when search should be bundled into the application and shipped like any other static asset. hnswlib is strongest when search is shared infrastructure with its own mutation path, observability, and security rules. Teams usually get the best outcome when they admit that those are materially different jobs.

Code comparison

altor-vec

import init, { WasmSearchEngine } from 'altor-vec';

await init();
const dim = 4;
const vectors = new Float32Array([
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
]);
const engine = WasmSearchEngine.from_vectors(vectors, dim, 16, 200, 50);
const hits = JSON.parse(engine.search(new Float32Array([0.95, 0.05, 0, 0]), 3));

hnswlib

import hnswlib

index = hnswlib.Index(space='cosine', dim=384)
index.init_index(max_elements=len(vectors), ef_construction=200, M=16)
index.add_items(vectors, ids)
labels, distances = index.knn_query(query_vector, k=3)

The syntax difference mirrors the architecture. With altor-vec, you initialize WASM, create or load a local index, and search with a Float32Array. With hnswlib, you usually authenticate to a service or rely on a backend process, then route your query through that environment. That adds network or runtime boundaries, but it also enables central governance and shared datasets. The “better” option depends on whether your search feature is fundamentally a frontend capability or a backend platform concern.

When to choose each

Choose altor-vec: Choose altor-vec when you want HNSW but need a package that fits the browser toolchain.

Choose hnswlib: Choose hnswlib when the system is already native or Python-based.

A hybrid model is common and healthy. Many teams keep browser-local semantic search for public docs, changelogs, release notes, or lightweight catalogs while using hnswlib for protected corpora, shared AI services, or complex operational search. That split respects the strengths of both systems instead of forcing everything into one stack just for conceptual purity.

Operational notes

Another practical difference is ownership. Frontend teams can usually ship altor-vec with existing static deployment infrastructure. hnswlib often pulls search into platform, DevOps, or backend ownership. That is not a downside when the product genuinely needs central control, but it is unnecessary drag when all you wanted was better semantic retrieval over public content.

When to choose each

Choose altor-vec when:

Choose HNSWlib when:

Performance characteristics

Both altor-vec and HNSWlib use HNSW with the same tuning parameters (M for graph connectivity, ef_construction for build quality, ef_search for query quality). At equivalent parameters, recall and precision are comparable.

Where they diverge is throughput. HNSWlib native C++ can execute millions of approximate nearest neighbor queries per second on a modern server. altor-vec WASM in the browser achieves thousands of queries per second — more than sufficient for interactive search (one query per keypress), but not suitable for batch processing millions of vectors server-side.

The more important performance axis for most use cases is end-to-end latency. altor-vec runs entirely in the browser runtime: a search takes 2–5ms with no network overhead. HNSWlib on a server adds the full network round-trip — typically 20–100ms depending on geography and infrastructure. For user-facing search boxes where perceived speed matters, altor-vec's WASM approach wins despite lower raw throughput.

Memory footprint: both hold the HNSW graph in RAM. A 10,000-vector index at 384 dimensions uses roughly 16MB of browser memory with altor-vec — well within modern browser limits. HNSWlib can handle much larger indexes by keeping them on disk (with memory-mapped files), which is not possible in the browser sandbox.

Technical architecture comparison

HNSWlib is a reference C++ implementation of the HNSW paper. It is accessed from Python via hnswlib Python bindings, which compile the C++ on install. The index lives in server memory (or on disk via memory-mapped files). Every search call is a native function invocation — no serialization, no IPC overhead.

altor-vec is compiled from Rust to WebAssembly using wasm-pack. The WASM binary is 54KB gzipped and runs inside the browser's WASM sandbox. JavaScript calls into the WASM module via the WebAssembly JS API. The index is built from a Float32Array passed from JavaScript, stored in WASM linear memory, and serialized to/from JSON for persistence.

The sandbox boundary matters for security: altor-vec cannot access the filesystem, network, or OS — it runs in the browser's isolated environment. This is a feature for browser search (user data stays on-device) and a limitation for server search (no disk index, no shared memory).

Migration guide

If you have an existing Python pipeline using HNSWlib and want to expose the same index in a browser frontend:

# Python: export index vectors from hnswlib
import hnswlib, numpy as np, json

index = hnswlib.Index(space='cosine', dim=384)
index.load_index('my_index.bin')

labels, _ = index.get_items(list(range(index.element_count)))
vectors = np.array(labels, dtype=np.float32)

# Save for browser consumption
np.save('public/vectors.npy', vectors)
with open('public/metadata.json', 'w') as f:
    json.dump(your_metadata_list, f)
// Browser: load vectors and build altor-vec index
import init, { WasmSearchEngine } from 'altor-vec';
await init();

const resp = await fetch('/vectors.npy');
const buffer = await resp.arrayBuffer();
// Parse npy header (148 bytes) then read float32 data
const vectors = new Float32Array(buffer, 148);
const engine = WasmSearchEngine.from_vectors(vectors, 384, 16, 200, 50);
const results = JSON.parse(engine.search(queryEmbedding, 5));

This lets your Python pipeline build the index offline and your browser frontend query it with zero server dependency at query time.

Bottom line

Use altor-vec when semantic retrieval belongs inside the interface and the browser is allowed to hold the index. Use hnswlib when search is a centralized system with private data, fast-changing writes, or operational requirements that the browser should not carry. That is the honest comparison axis, and it is the one that usually leads to the right architecture.

CTA: npm install altor-vec · Star on GitHub