
Narsil is an open-source distributed search engine. It auto-partitions large indexes across worker threads, serialises them into a cross-language binary format, and merges results into ranked answers. It runs on Node.js, Bun, Deno, and the browser, and it already runs in production: the Cmd+K search on this site and on both project documentation sites is Narsil. The documentation site walks through every feature, the source lives on GitHub, and the package installs from npm as @delali/narsil.
Four search modes in one engine
BM25 scoring supports field boosting, fuzzy matching via bounded Levenshtein distance, and term-coverage and score thresholds. Queries compose with filters, facets, sorting, grouping, highlighting, cursor pagination, pinned results, and autocomplete suggestions.
Cosine, dot product, and Euclidean queries start on an exact scan and promote to an HNSW graph as the field grows, with scalar quantisation on by default. Embedding adapters turn text into vectors automatically on insert and query, through OpenAI, local Transformers.js models, or your own adapter.
Hybrid queries fuse BM25 and vector rankings through reciprocal rank fusion or linear blending, tunable per query. You get the precision of keyword matching and the semantic reach of embeddings in a single ranked list.
Geo filters match by radius, using Haversine or Vincenty distance, or by polygon containment. They compose with every other query feature.
Benchmark results
Narsil competes in two classes. Served over HTTP against Elasticsearch, OpenSearch, Qdrant, Weaviate, Typesense, and Meilisearch on the BEIR datasets, its BM25 ranks level with the Lucene engines on SciFact, takes the top nDCG@10 on NFCorpus, and answers 1,020 keyword queries per second on one node. Embedded in one process, it takes the top nDCG@10 against Orama and MiniSearch. Its ranking reproduces the published Anserini baseline within 0.005 nDCG@10, and the full results come from a recorded continuous-integration run.
Partitioned indexes route documents by deterministic hash and reshape online through rebalance(), with writes buffering in a write-ahead queue during the reshape. Three scoring modes keep BM25 statistics honest when an index spans partitions or instances. The HTTP server subpath wraps the engine in a REST API with health probes, bulk NDJSON import, and snapshot and restore endpoints, while events, typed errors, plugins, and memory reporting cover observability. Language modules cover 39 languages as separate entry points, including Swahili with a full stemmer and eight more African languages with tokenisation and stop word support: Dagbani, Ewe, Ga, Hausa, Igbo, Twi (Akan), Yoruba, and Zulu.
Where this is going
Search is one of the most fundamental operations in computing, and the tools available today force you to choose between power and accessibility. Elasticsearch is powerful but operationally heavy. Lightweight libraries are easy to embed but collapse under production workloads. Narsil is built to be both: production-grade distributed search that you can embed in any runtime, in any language, without a separate cluster to manage.
The deeper ambition is language equity. The search infrastructure the world relies on was built around European languages, and billions of people are left with degraded results because their languages lack the stemmers, tokenisers, and stopword lists that English has had for decades. The nine African languages above are live today, alongside full support for Hindi, Tamil, Nepali, Sanskrit, and Indonesian. Full stemmers for the eight African languages that stop at tokenisation come next, built with native speakers and computational linguists. The goal is a search engine where a query in Twi returns results as precise as a query in English.


