Model or dataset
Stevenic/vectra avatar
Stevenic/vectra

Vectra: a file-backed vector database that needs no vector service

Vectra is a local vector database for Node.js with features similar to pinecone but built using local files.

633 stars51 forksTypeScriptMIT

At a glance

What is it?
Vectra is a local, file-backed vector database for Node.js and browsers where every index is a folder on disk, queries combine MongoDB-style metadata filtering with cosine similarity ranking, and an optional gRPC server exposes 19 RPCs for other languages. It is MIT licensed and runs against local files rather than a hosted vector service.
Who is it for?
Vectra fits a team that wants semantic search and retrieval over its own documents without running a hosted vector database or an embedding service, and it fits browser and Electron apps through the browser entry point and IndexedDB storage. It does not fit a large scale shared index, since the index is a local folder and the gRPC server is the only sharing mechanism, and local embedding quality depends on which model you point it at.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 95 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Vectra is and where it sits against a hosted vector service

Vectra is a local, file-backed, in-memory vector database with an optional gRPC server for cross-language access. The project description is blunt about the comparison: features similar to Pinecone but built using local files.

That distinction is the whole design. There is no cluster, no service to provision, no network round trip per query and no per-call billing. Each index is a folder on disk. The data lives in files you can copy, back up, mount into a container or read with other tools, and the querying happens in the same process that made the request.

The package description gives the shape of the API: a lightweight, file-backed vector database for Node.js and browsers with Pinecone-compatible filtering and hybrid BM25 search. The Pinecone-compatible part matters if you are porting an application that already filters vectors by metadata fields, because the filtering syntax carries over rather than being reinvented.

Queries use MongoDB-style metadata filtering and cosine similarity ranking, and the project states sub-millisecond latency for small indexes. That qualifier is doing real work in that sentence. The claim is scoped to small indexes, and the behaviour of a local file-backed index does not extend to millions of vectors in one folder.

The users are developers building retrieval augmented generation on top of their own documents, teams that want a vector store they can version and inspect, and browser or Electron applications where a hosted vector database is not an option.

The document index API from install to first query

Installation is one npm command:

bash
npm install vectra

The quick example in the documentation shows the whole flow with the document index and an OpenAI embeddings provider:

ts
import { LocalDocumentIndex, OpenAIEmbeddings } from 'vectra';

const docs = new LocalDocumentIndex({
  folderPath: './my-index',
  embeddings: new OpenAIEmbeddings({
    apiKey: process.env.OPENAI_API_KEY!,
    model: 'text-embedding-3-small',
    maxTokens: 8000,
  }),
});

if (!(await docs.isIndexCreated())) {
  await docs.createIndex({ version: 1 });
}

await docs.upsertDocument('doc://readme', 'Vectra is a local vector database...', 'md');

const results = await docs.queryDocuments('What is Vectra?', { maxDocuments: 5 });
if (results.length > 0) {
  const sections = await results[0].renderSections(2000, 1, true);
  console.log(sections[0].text);
}

Several design choices are visible. The index is created lazily and checked first with isIndexCreated, so the same code path works for a fresh folder and an existing one. The upsert takes a URI as the document key, a chunk of text and a format, here md. The query takes a natural language question and a limit on how many documents come back, and then the top result can be expanded into sections with renderSections, passing a size, an index and a flag.

The embeddings provider is injected rather than hard coded, which is the seam that makes the rest of the feature set possible. The API key comes from the environment, the model is named, and maxTokens bounds the input.

The library also exposes a local variant of the same interface, and the browser entry point swaps in IndexedDB storage for the file system, so the same application code can run in a browser tab.

Local embeddings and the browser entry point

The 0.14 release added two things that change who can use Vectra at all.

The first is the browser and Electron support through the vectra/browser entry point, which comes with IndexedDBStorage and TransformersEmbeddings. The package manifest backs this up: the exports map has a browser condition pointing at a separate build, the package carries a browser field, and there is a webpack.browser.js file in the tree.

The second is local embeddings. LocalEmbeddings and TransformersEmbeddings run HuggingFace models with no API key. That removes the two things that usually block a vector database from running client side, which are a network dependency and a secret in the bundle.

The trade-off is that embedding quality is now your problem. With OpenAI embeddings you get a hosted model; with the local transformers path you get whatever model you point the class at, and the result depends on that choice, on the machine's CPU, and on how the model is loaded. The documentation lists an embeddings guide as one of the maintained guides, with a note to choose and configure a provider there.

Combining the two is the interesting case. A browser application that indexes the user's own files locally, embeds them with a local model, and queries them without any server is a genuinely different application shape from a hosted vector database, and it is the shape the project seems to be built for.

The gRPC server, the language bindings and vectra serve

The optional gRPC server is what makes Vectra usable from something other than TypeScript.

The vectra serve command exposes 19 RPCs for cross-language access, and the vectra generate command scaffolds clients for six languages. The repository reflects that: there is a proto/ directory for the protocol definitions, a specs/ directory, and a samples/grpc-python/ directory, which shows a Python client working against the server.

The design is that the index stays on one machine, and other languages talk to it over gRPC rather than trying to reimplement the on-disk format. That is a sensible division of labour, because the on-disk layout is an implementation detail that would be expensive to keep stable across six client libraries.

It also means a Python or Go service does not get the in-process speed advantage. It pays a network hop, albeit a local one. If you are in Node.js, you use the library directly; if you are elsewhere, you run the server.

The command surface is documented in a CLI reference guide, with all CLI commands, flags and provider configuration, and there is a samples/ directory with runnable examples including a quickstart, a RAG pipeline, a browser sample, SQLite storage, gRPC and a folder watcher.

Document ingestion, FolderWatcher and hybrid search

The document indexing guide covers chunking, retrieval, hybrid search and the FolderWatcher.

The FolderWatcher auto-syncs directories into a document index, which is the feature that turns Vectra from a library you feed by hand into a local knowledge base over a folder of documents. The samples directory has a folder-watcher/ example and a wikipedia/ example, and there is a tutorials page covering folder sync among other topics.

The package description mentions hybrid BM25 search, and the query API supports metadata filtering alongside similarity ranking. That combination is the practical part. Pure vector search finds text that means the same thing, and BM25 finds text that uses the same words, and a retrieval system that relies on embeddings alone tends to miss exact identifiers, error codes and product names, which is exactly what a keyword ranking catches.

The package manifest lists bm25, hybrid-search, cosine-similarity, rag and retrieval-augmented-generation among its keywords, and there is a rag/ sample. A dedicated custom-storage/ sample is there too, matching the storage guide's promise of pluggable backends.

The v0.15 release focused on performance, with skip-if-unchanged document upserts, shallow-clone transactional snapshots, heap-based top-K query ranking, parallel metadata loads and O(N) batch chunk deletion. That is a list of internal optimisations rather than new features, which tells you the API was considered stable by then.

Where Vectra is the wrong tool

The first limit is scale and sharing. The index is a folder on disk and the library loads it in memory, and the latency claim is scoped to small indexes. A multi user product where many processes need to query the same large corpus needs a shared vector service, and a local folder with a gRPC server in front of it is a single machine architecture with the concurrency limits that implies.

The second is that the in-memory model means startup cost scales with the index. The documentation's best practices guide covers performance tuning and troubleshooting, and the v0.15 notes mention shallow-clone transactional snapshots, which suggests a copy-on-write style snapshot per transaction. That is cheap for a small index and expensive for a large one.

The third is the dependency on an embeddings provider. With the OpenAI path you have a network call, an API key and a per-token cost, and you are sending your documents to a hosted service. With the local path you have a model to choose, ship and load, and quality that depends on it. Vectra does not remove that decision, it only makes both answers available.

The fourth is the maturity of the version line. The releases are 0.12.0 in January 2026, 0.14.0 in April and 0.15.0 in May 2026, with the last push on 2026-07-20. A pre-1.0 line with a changelog that carries breaking changes and migration guides is normal for this stage, and it means you should read the changelog before following an upgrade path rather than assuming semver compatibility.

Compare that with running a hosted vector database. The difference in approach is that a hosted service gives you a shared, scaled, always available index with a managed embedding and upsert pipeline, and charges you for it, whereas Vectra gives you files, no per-call cost and no network, and asks you to own the index lifecycle, the embedding model and the machine.

Licence, the llms.txt file and the cost of an upgrade

Vectra is released under the MIT License, with the text in the LICENSE file at the repository root, and the package manifest repeats the same identifier. The MIT terms allow use, modification and redistribution including inside a closed source product, provided the copyright notice and licence text travel with copies. Read the LICENSE file yourself for the exact wording.

The package is published as vectra with version 0.15.0, authored by Steven Ickman, and the manifest declares a bin entry of vectra pointing at the CLI script, which is how vectra serve and vectra generate are invoked. The engines field requires a recent Node.js version, and the exports map has separate node, browser and default conditions so the browser build does not drag Node-only code into a bundle.

The llms.txt file is the detail worth knowing about. The project ships one that gives coding agents everything they need to integrate Vectra, covering all exports, index types, CLI commands, gRPC bindings and the on-disk format. The documentation suggests pointing an agent at it with a short instruction, and the repository has an llms.txt file at the root, plus an AGENTS.md, a CLAUDE.md, a .cursorrules file and a .windsurfrules file, which is a lot of agent integration surface for a small library.

The upgrade cost sits in two places. The changelog carries breaking changes and migration details for the 0.14 and 0.15 line, so a jump from an earlier version is a migration task. And because the on-disk format is part of the contract, an index written by one version may need regenerating after a format change, which is the operational detail to check before you rely on a long-lived index folder.

Editorial conclusion

Vectra fits a team that wants semantic search and retrieval over its own documents without running a hosted vector database or an embedding service, and it fits browser and Electron apps through the browser entry point and IndexedDB storage. It does not fit a large scale shared index, since the index is a local folder and the gRPC server is the only sharing mechanism, and local embedding quality depends on which model you point it at. Before adopting it, confirm your embedding provider choice and whether its key management suits your deployment, test the hybrid BM25 and cosine paths against your own queries, and read the changelog before moving past 0.14, since 0.14 and 0.15 carry breaking change notes.

Frequently asked questions

How do I install Vectra and create a local vector index?

Run npm install vectra, then create a LocalDocumentIndex with a folderPath and an embeddings provider, call createIndex({ version: 1 }) if isIndexCreated() returns false, and upsert documents with upsertDocument. Queries go through queryDocuments with a maxDocuments limit.

Can Vectra run without a hosted embedding API?

Yes. The project documents LocalEmbeddings and TransformersEmbeddings, which run HuggingFace models with no API key, and the vectra/browser entry point pairs that with IndexedDBStorage for browser and Electron use.

How do I use Vectra from a language other than TypeScript?

Run vectra serve, which exposes 19 RPCs over gRPC for cross-language access, and use vectra generate to scaffold a client for one of six languages. The repository includes a proto directory and a grpc-python sample showing a Python client.

What filtering and search does the Vectra query API support?

Queries combine MongoDB-style metadata filtering with cosine similarity ranking, and the package description also lists hybrid BM25 search. The FolderWatcher feature auto-syncs directories into a document index.

What licence does Vectra use?

Vectra is released under the MIT License, with the terms in the LICENSE file at the repository root and the same identifier in the package manifest.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. Stevenic/vectra on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stevenic-vectra.svg)](https://hysenlabs.com/projects/stevenic-vectra)

Was this useful?