altor-vec vs elasticlunr

altor-vec vs Elasticlunr — Semantic Search vs Extended Full-Text Search

Q: Is altor-vec better than Elasticlunr for JavaScript search?
A: It depends on your search requirements. Elasticlunr is well-suited for keyword-based full-text search with field boosting over static site content. altor-vec is the better fit when meaning matters more than exact word matches, when users search in their own vocabulary rather than the document vocabulary, or when you need a more actively maintained solution.

Elasticlunr.js is a fork of lunr.js that adds more flexibility around indexing and ranking, including field boosting, configurable scoring behavior, and incremental indexing. That makes it a strong keyword search library for static sites and documentation pages that already use the lunr ecosystem. The core distinction, though, is not lunr vs newer lunr. It is TF-IDF style lexical retrieval vs vector retrieval. Elasticlunr ranks documents by overlapping terms and term importance. altor-vec ranks documents by semantic proximity in embedding space using HNSW, so related meaning can match even when the words differ.

Install altor-vec: npm install altor-vec

Feature comparison table

Capabilityaltor-vecElasticlunr
AlgorithmHNSW vector similarity over embeddingsTF-IDF with BM25-like scoring over an inverted index
Semantic understandingYes, meaning-based retrievalNo, literal term matching only
Bundle size54KB gzipped WASM~18KB minified
Maintenance statusActively maintainedLargely in maintenance mode since around 2017
Field boostingNo native field boosting modelYes
Incremental indexingNo, indexes are typically built ahead of timeYes
Build step requiredUsually yes, to generate embeddings and serialize the indexNo build step required for basic usage
Works offlineYesYes
LicenseMITMIT

Elasticlunr became popular because it extends the lunr model without giving up the static-site friendliness developers liked in Gatsby, Hugo, and Jekyll workflows. You can build an index in JavaScript, boost titles above body text, and ship search with almost no moving parts. That is still a valid reason to choose it. The limitation is conceptual, not cosmetic. If a user searches for cancel subscription and your article is titled end your plan, Elasticlunr has no semantic bridge between those phrases unless your content already contains overlapping terms.

altor-vec is solving a different retrieval problem. Instead of asking whether the query string overlaps with indexed text, it asks whether the query vector is close to document vectors that represent similar meaning. That changes what search feels like in practice. Users can search with their own phrasing, internal docs can use a different vocabulary than customer-facing copy, and relevant results can still surface. For developer docs, help centers, changelogs, and knowledge bases, that can reduce the common failure mode where the right page exists but the search box never connects the wording.

What changes in practice

Elasticlunr mindset

You tune fields, stemming, and boosts so exact words and close lexical variants rise to the top. Search quality improves when documents contain the same words users are likely to type.

altor-vec mindset

You tune embeddings, chunk boundaries, and corpus quality so the vector index captures intent. Search quality improves when related concepts land near each other even if wording changes.

When to migrate

Teams usually migrate when search analytics show reformulated queries, no-result searches, or poor click-through caused by vocabulary mismatch rather than typo handling or indexing bugs.

Code comparison

altor-vec

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

await init();
const response = await fetch('/search-index.bin');
const engine = WasmSearchEngine.from_bytes(
  new Uint8Array(await response.arrayBuffer())
);

// Semantic match can find "end your plan" for "cancel subscription"
const hits = JSON.parse(engine.search(queryEmbedding, 5));

Elasticlunr

var elasticlunr = require('elasticlunr');
var index = elasticlunr(function () {
  this.addField('title');
  this.addField('content');
  this.setRef('id');
});
docs.forEach(doc => index.addDoc(doc));
// Keyword match only -- will not find "end your plan" for "cancel subscription"
var results = index.search('cancel subscription', { expand: true });

The Elasticlunr snippet shows why it remains attractive. The index is easy to define, the documents stay as plain objects, and search runs immediately on lexical tokens. There is no embedding pipeline and no binary artifact to ship. altor-vec asks you to do more work before runtime, but that up-front cost is what unlocks semantic retrieval, stronger scaling with approximate nearest-neighbour search, and better behavior for synonym-heavy or intent-heavy search patterns.

When to choose each

Choose Elasticlunr when:

Choose altor-vec when:

The honest tradeoff is straightforward. Elasticlunr wins on simpler setup, smaller bundle size, and compatibility with the lunr-style ecosystem. altor-vec wins on semantic understanding, active maintenance, and scaling characteristics that fit larger or more language-diverse corpora. If your users mostly search with exact product terminology, Elasticlunr can still be the right tool. If they search with natural language, semantic retrieval tends to feel more helpful much faster.

Migrating from Elasticlunr

  1. Audit your current query logs. Confirm whether search failures come from missing documents or from vocabulary mismatch, because semantic search only pays off if meaning mismatch is the real problem.
  2. Export the same content you already index. Titles, headings, summaries, and body text can be reused, but they now need embeddings generated at build time instead of only tokenization.
  3. Generate vectors and serialize the index. Build an altor-vec index ahead of deployment, then serve it as a static asset alongside your site.
  4. Swap the retrieval layer, keep the UI stable. Reuse your existing search modal or results page first, then measure changes in no-result rate, refinement rate, and successful clicks.
  5. Add fallback behavior where needed. Some teams keep lexical highlighting or exact-match boosting in the interface while altor-vec handles the core ranking.

FAQ

What is the difference between altor-vec and Elasticlunr?

Elasticlunr extends lunr.js with field boosting, configurable scoring, and incremental indexing. It is a TF-IDF based full-text search library that matches queries against literal terms in documents. altor-vec uses HNSW vector search to find documents by meaning, not word overlap. Searching plan pricing finds subscription cost in altor-vec but not in Elasticlunr.

Is Elasticlunr still actively maintained?

Elasticlunr.js has been largely in maintenance mode since around 2017. The core library is stable for many use cases, but it receives few updates. altor-vec is actively maintained with regular releases. For projects starting fresh, the maintenance gap is worth factoring into the decision.

Can Elasticlunr understand synonyms or related terms?

No. Like lunr.js, Elasticlunr uses inverted index and TF-IDF scoring. It can only match documents that contain the literal query terms or their stems. To get synonym support, you need to preprocess documents with a synonym list or switch to a semantic search engine like altor-vec.

How do bundle sizes compare between altor-vec and Elasticlunr?

Elasticlunr is approximately 18KB minified. altor-vec ships as a 54KB gzipped WebAssembly bundle. Elasticlunr is lighter and has no build step; altor-vec is larger but provides semantic retrieval that TF-IDF cannot replicate.

Bottom line

If you are comparing an Elasticlunr alternative for modern JavaScript search, the choice comes down to lexical flexibility versus semantic relevance. Elasticlunr is still a solid full-text library when you want a lightweight, offline, lunr-compatible search box. altor-vec is the better fit when you want the search box to understand intent, bridge vocabulary gaps, and sit on a more actively maintained foundation.

CTA: Use npm install altor-vec when you need semantic retrieval in the browser, then compare it against your current Elasticlunr results on real queries.