BL

bleve

Embeddable full-text search and indexing library

Search Engines ★ 11.2k stars Medium setup Apache-2.0

An embeddable modern full-text search and indexing library that lets developers add search to applications without running a separate server. It supports analyzers, faceting, and scoring out of the box.

Key features

  • Embeddable index
  • Text analyzers
  • Faceted search
  • Pluggable storage

Pros & cons

Strengths

  • No separate server
  • Pure Go integration

Trade-offs

  • Library not turnkey app
  • Manual scaling

bleve replaces

Last reviewed Aug 26, 2026 · 832 words

Bleve is not something you deploy. It is a Go library that a program links into itself to get full-text search without running a separate server, and the reason it belongs in a self-hosting catalogue is that you are almost certainly running it already: Gitea and Forgejo use it as the default indexer for issues and, optionally, code; Mattermost offers it as the lightweight alternative to Elasticsearch; Couchbase built its full-text service on it. Understanding what it is, and what it is not, tells you when an app's "search" setting can be left alone and when you need a real search server beside it. The catalogue title for this entry is muddled (it mentions Sonic and Meilisearch, which are separate projects); the software described is Bleve, Apache-2.0, 11,186 stars, first released in 2014.

Where it sits in a stack

An application with Bleve embedded keeps its index as a directory on disk next to its own data (the default storage engine is called scorch), opens it at startup, and answers queries in-process. There is no port, no daemon, no client library, and nothing extra to back up beyond the directory, which can usually be rebuilt from the source data anyway. Memory use is whatever the index needs; the 128 MB figure in the catalogue is a fair floor for a few hundred thousand documents.

For a self-hoster the practical consequence is that a Gitea instance with 5,000 issues gets acceptable search with zero configuration, and switching ISSUE_INDEXER_TYPE to elasticsearch or meilisearch in app.ini is only worth doing once the repository count runs into the thousands or the code indexer is turned on for large monorepos. The same logic applies to any application that offers "built-in" search: it is very likely Bleve, and it is fine until it is not.

What a developer gets for 10 lines

If you write Go, this is the whole API for a working index:

mapping := bleve.NewIndexMapping()
index, err := bleve.New("notes.bleve", mapping)
if err != nil { log.Fatal(err) }

index.Index("note-42", map[string]any{
    "title": "Restic restore runbook",
    "body":  "Steps to restore the homelab from B2",
    "tags":  []string{"backup", "restic"},
})

q := bleve.NewMatchQuery("restore backup")
res, err := index.Search(bleve.NewSearchRequest(q))

Analyzers (stemming, stop words, language-specific tokenisers), faceting by field, phrase and fuzzy queries, boolean combinations, highlighting and BM25 scoring are all in the box. A custom mapping declares which fields are text, which are keywords and which are dates, and getting that mapping right is 90% of the difference between search that feels sharp and search that returns everything. Storage is pluggable, but in practice everyone uses scorch on local disk.

What it is not

Bleve does not scale horizontally. One process owns the index directory; two replicas of your app each need their own copy, and there is no built-in replication, which is what the catalogue means by "manual scaling". It has no HTTP API, so nothing outside the host program can query it, and no dashboard. Typo tolerance exists as fuzzy queries with an edit distance you set, not the automatic kind that makes Meilisearch and Typesense feel instant on a search-as-you-type box. Vector search arrived in recent versions, but for anything serious in that direction the embeddings in production piece is the better starting point. Index rebuilds on a large corpus are slow enough that applications wrapping Bleve usually run them as a background job with a progress indicator.

When to embed versus when to run a server

Embed Bleve when the search lives inside one Go application, the corpus is under a few million documents, and you want zero additional operational surface: a personal notes tool, a small CMS, an internal document index. Run a server when several applications need the same index, when the app is not Go, when you want typo-tolerant instant search in a browser, or when the index must survive the application being scaled out. In that case Meilisearch is the friendly default, Typesense the faster one at scale, Sonic the tiny one when you only need identifiers back, and Manticore the SQL-flavoured one; the search category walks through the split.

What I'd do

Leave every application's built-in Bleve search alone until it is measurably slow, and check the app's own docs for the switch to an external engine before assuming one is needed; on Gitea that is a one-line change and a re-index. If I were writing my own Go tool that needed search, Bleve is what I would reach for first, with a hand-written mapping and a rebuild-from-source command, and I would only add Meilisearch if a second app needed the same data. It is boring infrastructure in the best sense, and the correct amount of attention to pay it is almost none.

Compare bleve

28 head-to-head comparisons.

Similar search engines apps