Open-source project
oramasearch/orama avatar
oramasearch/orama

Orama: a TypeScript search engine that runs in the browser, on the server or at the edge

🌌 A complete search engine and RAG pipeline in your browser, server or edge network with support for full-text, vector, and hybrid search in less than 2kb.

10,553 stars403 forksTypeScriptNOASSERTION

At a glance

What is it?
Orama is an embeddable search library for JavaScript and TypeScript with full-text, vector and hybrid modes, a declarative schema and a plugin system. It suits teams that want search inside their own process, and it fits badly when the index has to outlive a single process.
Who is it for?
Adopt Orama when the index belongs to one process: a browser app, a serverless function, an edge worker, or a Node service that rebuilds its data on boot. Do not adopt it when several processes must share one index, when you need server-side ranking control or analytics, or when you expect the same documents to survive a redeploy without you persisting them.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 5 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 September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What Orama is for, and who ends up using it

Orama is a search engine implemented as a library rather than a service. The package description calls it "a complete search engine and RAG pipeline in your browser, server, or edge network with support for full-text, vector, and hybrid search in less than 2kb". That sentence is the whole product thesis: search runs in the same process as your application, so there is no network hop to a search cluster and no separate index to operate.

The people who get value from that are specific. A frontend engineer building a documentation site or a product catalogue wants substring and typo-tolerant matching without standing up Elasticsearch. A backend engineer on a serverless platform wants to search a few thousand rows that already arrived in the request payload. Someone building a retrieval step for a chat feature wants vector search next to the same documents they are already indexing for keyword search. In all three cases the dataset is bounded and the process is short-lived.

The mismatch appears when the dataset is not bounded. Orama has no server component in this repository, so there is nothing to which a second process can connect. If two instances of your application need to see the same index, the synchronization is yours to build.

Schema first: how Orama indexes a document

Orama is schema-driven. Before inserting anything you call create() with a schema object that maps field names to types. The README lists ten supported types: string, number, boolean, enum, geopoint, string[], number[], boolean[], enum[], and vector[<size>]. Nested objects are allowed, as the usage example shows with a meta object containing a rating number.

The vector type is the one that constrains you at design time. The comment in the README is explicit: "Vector size must be expressed during schema initialization". A field declared as vector[1536] accepts 1536-dimensional embeddings and nothing else. If you later switch embedding model and the dimension changes, the schema changes with it.

Insertion is a plain function call. insert() takes the database and one document; insertMultiple() takes an array. There is no batching protocol, no bulk endpoint, and no background merge step to wait on. Search is likewise a function: search(db, { term: 'Best headphones' }) returns an object with hits, count, and an elapsed field containing raw microseconds and a formatted string such as '21μs'.

That elapsed value is worth reading carefully. It measures the search call itself, not indexing and not the time your application spent producing embeddings. The README's example output shows elapsed.raw: 21492 and elapsed.formatted: '21μs', which is a number from one run on one machine, not a published benchmark.

Installing Orama and running a first hybrid query

The README gives four package managers and two runtime-native paths. For a Node or bundler-based project the install is a single package:

bash
npm i @orama/orama

For a browser page with no build step, the README imports the same functions from a CDN module URL:

html
<html>
  <body>
    <script type="module">
      import { create, insert, search } from 'https://cdn.jsdelivr.net/npm/@orama/orama@latest/+esm'
    </script>
  </body>
</html>

Deno gets the same entry points through npm specifiers, as the README shows:

js
import { create, search, insert } from 'npm:@orama/orama'

With the package installed, the first real use is to declare a schema that covers both your text fields and your embedding field, then insert documents. The README's vector example uses a deliberately small five-dimensional vector so the numbers fit on screen:

js
import { create, insertMultiple, search } from '@orama/orama'

const db = create({
  schema: {
    title: 'string',
    embedding: 'vector[5]',
  },
});

insertMultiple(db, [
  { title: 'The Prestige', embedding: [0.938293, 0.284951, 0.348264, 0.948276, 0.56472] },
  { title: 'Barbie', embedding: [0.192839, 0.028471, 0.284738, 0.937463, 0.092827] },
  { title: 'Oppenheimer', embedding: [0.827391, 0.927381, 0.001982, 0.983821, 0.294841] },
])

To search those vectors you call search() with mode: 'vector'. The README states that vector and hybrid search are selected by setting mode: 'vector' at search time, and that you must supply the query embedding yourself. Orama does not generate embeddings. That is a deliberate boundary: the library indexes and ranks, and an external model or API produces the vectors.

Where Orama stops being the right tool

The most consequential limitation is that the index lives in memory, in the process that created it. Nothing in the README describes a server, a replication protocol, or a shared index format that two processes can open. A search from a second process means a second index, built from the same source data, with whatever drift that implies.

That has a direct consequence for serverless deployments. A function that creates a database and inserts documents on every cold start pays the indexing cost on every cold start. The README's quick-start example does exactly this, and it is the correct shape for a demo, but it is not a persistence strategy. If your documents are large or numerous, the cost lands on user-facing latency.

Embedding generation is the second boundary. Vector and hybrid search require you to bring your own vectors, and the README links out to a general explanation of text embeddings rather than shipping a model. Every insert of a vector field and every vector query therefore depends on a component Orama does not control.

Third, the feature list is broad but each entry points at documentation rather than at guarantees. Facets, geosearch, pinning rules, field boosting, BM25, stemming and tokenization in 30 languages, and a plugin system are all advertised. The README itself does not specify their behaviour, their interaction, or their performance characteristics. That is a documentation boundary, not evidence that they are weak, but it means the README alone cannot tell you whether a particular combination works for your data.

Orama against a hosted search API

The natural alternative is a hosted search service such as Algolia, and the difference is architectural rather than a matter of features. A hosted service keeps the index on its own infrastructure and exposes it over HTTP. Your application sends a query and receives results. Orama keeps the index inside your application and exposes it as function calls.

The trade is easy to state. With a hosted API you get one index that many clients share, server-side control over ranking and relevance, and an operational surface that is not your problem. You also get a network round trip on every query, a per-request cost model, and a copy of your data on someone else's machines. With Orama you get zero network latency between your code and the index, no per-query billing, and complete data locality. You also get the responsibility for building the index, persisting it if the process is short-lived, and keeping it consistent with your source of truth.

There is a telling detail in the repository's package.json. Under pnpm.peerDependencyRules.ignoreMissing, the first entry is "@algolia/client-search". That is a workspace configuration artifact, not a product statement, but it does confirm that the monorepo's tooling is aware of the Algolia client package and deliberately does not require it. Orama's own positioning is that you do not need that dependency.

Licence, monorepo layout and the cost of upgrading

The repository's package.json declares "license": "Apache-2.0", while the repository metadata carries NOASSERTION. Those two signals disagree, and the practical answer is to read LICENSE.md at the repository root before you depend on the package commercially. Apache-2.0 is a permissive licence with an explicit patent grant and a requirement to preserve notices; that is the shape the package manifest claims. This is not legal advice, and the NOASSERTION marker means an automated classifier did not confirm the file, so the file itself is the authority.

Upgrade cost is shaped by the release cadence. The most recent releases listed are v3.1.18 on 2025-12-19, v3.1.17 on 2025-12-14, and v3.1.16 on 2025-10-13, while the root package.json carries version 3.2.0. Patch releases arrive close together at times, which is normal for a library of this size and means you should pin a version rather than float on latest. The repository uses changesets (.changeset/ is a top-level directory) and a CHANGELOG.md, so version-to-version changes are recorded rather than left to inference.

Building from source is a pnpm and Turborepo affair: pnpm-workspace.yaml and turbo.json at the root, with packages/ and sandboxes/ as workspaces. The scripts are turbo build, turbo lint, and turbo test. That matters only if you intend to patch the library; consumers install the published package and never touch the workspace. The last push to the repository was on 2026-09-11.

Editorial conclusion

Adopt Orama when the index belongs to one process: a browser app, a serverless function, an edge worker, or a Node service that rebuilds its data on boot. Do not adopt it when several processes must share one index, when you need server-side ranking control or analytics, or when you expect the same documents to survive a redeploy without you persisting them. Before committing, verify three things in your own environment: that the schema you write matches the query modes you intend to run, that your embedding dimension fits the vector[<size>] declaration, and that you have a place to serialize the index if the process is short-lived.

Frequently asked questions

What is Orama?

Orama is a search engine packaged as a JavaScript and TypeScript library. Its package description calls it a complete search engine and RAG pipeline for the browser, server or edge network, with full-text, vector and hybrid search in less than 2kb.

How do I install Orama?

The README gives npm i @orama/orama for npm, yarn, pnpm and bun. It also documents a browser module import from the jsDelivr CDN and a Deno import using the npm:@orama/orama specifier.

Does Orama support vector search?

Yes. The README lists vector search and hybrid search as highlighted features and states that you select them by setting mode: 'vector' when performing a search. You must supply the text embeddings yourself at search time.

What does Orama mean?

The repository does not explain the origin of the name. Its README and package.json describe the project's capabilities and installation only, so the etymology is not documented in the files published with the project.

Official sources

  1. Issues
  2. oramasearch/orama on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes