Whoosh vs Tantivy (tantivy-py): which should you use for full-text search in Python?

by Priya Sundaram · 14 July 2026
Short answer: If raw indexing and query throughput on large corpora is your priority — and you're happy to depend on a compiled Rust engine — reach for Tantivy via its Python bindings, tantivy-py. If you want a search engine you can read, extend, and debug entirely in Python, that installs with a plain pip install on any platform with no compiler and no native code, and that runs on PyPy and even in the browser via WebAssembly, choose Whoosh. They're both good; they optimise for different things.

Once you've decided you don't need a separate service like Elasticsearch or OpenSearch, the two most common embeddable, in-process options in the Python world are Whoosh and Tantivy (through tantivy-py). This is a practical guide to choosing between them.

The one-line difference

At a glance

 Whoosh (whoosh3)Tantivy (tantivy-py)
ImplementationPure PythonRust core + Python bindings
Installpip install whoosh3 — pure wheel, works everywhere CPython runspip install tantivy — prebuilt wheels for common platforms; falls back to building from source (needs a Rust toolchain) when no wheel matches
Runtime depsNoneCompiled extension module
Raw speedGood for thousands to low-millions of docs; it's Python, so it won't match native codeVery fast; built for high indexing and query throughput on large corpora
RankingBM25F (default), TF-IDF, pluggable in PythonBM25
Query languageRich built-in parser: boolean, phrase, range, wildcard, fuzzy, fieldsQuery parser plus programmatic query building
Analysis / stemmingComposable analyzers, stemming, stop words, n-grams — all in Python and easy to customiseConfigurable tokenizers/filters exposed by the Rust engine
HighlightingYes, built inSnippet generation available
Faceting / groupingYesYes (aggregations)
Spelling / "did you mean?"Yes, built inNot a built-in library feature
PyPyRuns (pure Python)Depends on the compiled extension working under PyPy
Browser / WebAssembly (Pyodide)Yes — Whoosh runs in the browser; there's a live demoNot a typical target for the bindings
Best fitEmbedded search you program in Python; portability matters more than peak speedLarge corpora and high query volume where native performance matters
On benchmarks — an honest note. I'm not going to hand you a made-up head-to-head number. Tantivy is a Rust engine and, for large indexes and heavy query loads, it will comfortably out-perform any pure-Python engine, including Whoosh — that's the expected outcome and it's the whole point of binding to native code. If throughput at scale is your deciding factor, that answer is already clear. What Whoosh trades that speed for is portability and programmability, which is what the rest of this page is about. If you want a reproducible Whoosh baseline on your own data, the repo ships examples/benchmark_vs_sqlite.py you can adapt.

Where Whoosh wins

Where Tantivy wins

Same task, both libraries

Indexing two documents and running a query looks broadly similar in each. Whoosh:

from whoosh.fields import Schema, TEXT, ID
from whoosh.index import create_in
from whoosh.qparser import QueryParser
import os, tempfile

d = tempfile.mkdtemp()
schema = Schema(title=TEXT(stored=True), body=TEXT)
ix = create_in(d, schema)

w = ix.writer()
w.add_document(title="First", body="the quick brown fox")
w.add_document(title="Second", body="a lazy brown dog")
w.commit()

with ix.searcher() as s:
    q = QueryParser("body", ix.schema).parse("brown")
    for hit in s.search(q):
        print(hit["title"])

Tantivy (tantivy-py), sketched from its documented API:

import tantivy

builder = tantivy.SchemaBuilder()
builder.add_text_field("title", stored=True)
builder.add_text_field("body", stored=False)
schema = builder.build()

index = tantivy.Index(schema)
writer = index.writer()
writer.add_document(tantivy.Document(title="First", body="the quick brown fox"))
writer.add_document(tantivy.Document(title="Second", body="a lazy brown dog"))
writer.commit()

index.reload()
searcher = index.searcher()
query = index.parse_query("brown", ["body"])
for _score, addr in searcher.search(query, 10).hits:
    print(searcher.doc(addr)["title"][0])

How to choose

Pick Tantivy if:

Pick Whoosh if:

It isn't strictly either/or. Plenty of projects prototype and ship with Whoosh for its simplicity, and only reach for a native engine if and when scale actually demands it.

Whoosh is maintained again. It's pure Python, zero runtime dependencies, BSD-2-Clause, with a live browser demo and modern packaging.

⭐ Star Whoosh on GitHub  ·  Try the live demo  ·  pip install whoosh3

See also: Whoosh vs SQLite FTS5.