Self-hosted service
spotify/voyager avatar
spotify/voyager

Voyager: one HNSW index across Python and Java

🛰️ An approximate nearest-neighbor search library for Python and Java with a focus on ease of use, simplicity, and deployability.

1,604 stars89 forksC++Apache-2.0

At a glance

What is it?
Spotify built Voyager as an approximate nearest-neighbour library whose Python and Java bindings share one C++ core and one index, aimed at services that search embeddings already held in memory.
Who is it for?
Engineers who already run HNSW indexes and need one index shared between a Python service and a Java service have a library that fits, with parity and index compatibility as its headline promise.
Can I use it commercially?
Yes. Apache-2.0 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 3 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • spotify/voyager1,604 ★ · -2
Star history
Repository2026-10-142026-10-23
spotify/voyager1.6k1.6k

-2 Stars in the last 9 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

What in-memory nearest-neighbour search changes for embedding workloads

An approximate nearest-neighbour library only earns its place when the same query runs millions of times against data already resident in memory. Voyager is scoped exactly there: a library for fast approximate nearest-neighbour searches over an in-memory collection of vectors, with ease of use, simplicity and deployability named as its priorities. Teams doing recommendation lookups, similarity search or retrieval over embeddings already held in RAM are the audience. Anyone wanting a durable vector store with an index on disk is not, because nothing in the project description promises persistence, and the README never shows an index being written to a file. The README also states that Voyager runs in production at Spotify and is queried hundreds of millions of times per day for user-facing features, which sets the expectation of a cheap per-call path rather than a batch engine.

A C++ core with parity across Python and Java

The heavy lifting is C++, and the root listing shows cpp/, python/ and java/ sitting side by side with docs/ and benchmarks/. The index structure is HNSW, taken from the open-source hnswlib package and extended with features added for convenience and speed. Two properties matter more than the algorithm name for most adopters: feature parity and index compatibility between the two bindings. That pair is what lets a single index serve a Python pipeline and a Java serving tier without a conversion step, and it is why the two languages are described together rather than as independent ports. A benchmark configuration file, asv.conf.json, sits beside benchmarks/ at the root, so the tree carries its own measurement setup, although no figures from it appear on the repository page.

pip install voyager plus Maven and sbt coordinates

Python installs from PyPI in one command:

shell
pip install voyager

That is the whole Python path. No build step, no compiler requirement and no environment variables are listed for it. Java goes through Maven, and this is the artifact block the README tells you to add to your build file:

xml
<dependency>
  <groupId>com.spotify</groupId>
  <artifactId>voyager</artifactId>
  <version>2.1.0</version>
</dependency>

Scala builds take the same artifact through sbt:

sbt
"com.spotify" % "voyager" % "2.1.0"

Both snippets pin 2.1.0, so copying them gives you that exact build rather than a moving target. After the install there is no example left to copy, which is the problem the next section is about.

Index construction and queries stay off the README page

The README covers installation and a platform table, then stops. Everything about the first real use lives elsewhere, split across a Python page and a Java page on the documentation site at https://spotify.github.io/voyager/. Nothing on the repository page shows how to create an index, insert vectors, widen or narrow the search, or read results back, and there is no sample script to adapt. The project's topic tags are hnsw, hnswlib, java, machine-learning, nearest-neighbor-search and python, so the indexing surface is real, but its shape is not visible from what the repository publishes. For a reader weighing adoption, that documentation site is the first thing to open, before any install command is run.

The support table leaves Windows arm64 unfilled

Read down the arm64 column and the three operating systems behave differently. Linux and macOS carry a check for Python 3.9 through 3.13 and for Java 8-16+, on both x86_64 and arm64. Every Windows row, all five Python versions and the Java row, carries a cross on arm64. A team standardising on Windows laptops therefore has no listed build for an ARM machine, and the Apple Silicon badge in the README covers macOS and Linux, naming Docker in its text. The same table also sets the floor at 3.9 for Python, so an older interpreter sits outside the support matrix rather than in an untested corner. Anything needing more precision than approximate search is equally out of scope.

Why the README sets Annoy and Sparkey side by side

The project makes its own comparisons in one sentence: Sparkey as the model of a small in-process store, and Annoy, which shares the same owner, as the recall trade-off. The second comparison is the substantive one, because Voyager moves the same search job onto HNSW, a graph search taken from hnswlib, and claims much higher recall. That claim cannot be checked from the repository: no recall figure, latency number or dataset appears anywhere in the README, which instead sends readers to http://ann-benchmarks.com/. Treat the comparison as a pointer, not evidence, and measure on your own vectors before choosing, since a library page that promises higher recall without naming index parameters cannot settle the argument for you.

The README's own links still say master, not main

A close reading turns up mismatches a skim passes over. The repository default branch is main, yet the badge link at the top of the page and the contributing link both resolve through a master path, blob/master/CONTRIBUTING.md being one of them, so those links were written against an older branch name. The Java and Scala snippets pin 2.1.0, and the last push was on 2026-09-17 while the newest published build, v2.1.1, carries a date of 2025-09-23, which means a copy-paste install lands well behind the branch tip. Both facts are cheap to confirm yourself: open the branch, open the newest build, and compare them with whatever your own build file already pins.

Repository files that sit outside the two language trees

The root listing shows how little of the tree is a language binding. There is .clang-format for C++ formatting, CODE_OF_CONDUCT.md and OWNERS.md for project governance, a docs/ tree for the site the README points at, and benchmarks/ with asv.conf.json beside it. A .gitmodules file records vendored submodules, and nothing in the README names which dependency that file covers, so anyone building from source has to read it there. Voyager is labelled Apache-2.0, yet the licence line renders the words Apache 2 License over a link that resolves to the GNU GPL page, with the Apache URL nested inside the link text, so the licence a reader clicks through and the licence a reader assumes are not the same document. Copyright is stated as 2022-2024 Spotify AB.

Editorial conclusion

Engineers who already run HNSW indexes and need one index shared between a Python service and a Java service have a library that fits, with parity and index compatibility as its headline promise. Teams that want a documented index-building example, a Windows arm64 build or recall figures before installing will not find them in the repository, so read the Python and Java pages at spotify.github.io/voyager/ first, pin your own version instead of copying the snippet, and open .gitmodules before building from source.

Frequently asked questions

Can Voyager use one index from both Python and Java?

Yes. The project states that the Python and Java bindings come with feature parity and index compatibility, so an index built in one language can be read in the other. Both sit on the same C++ core.

Which Python versions and operating systems does Voyager support?

The support table lists Python 3.9 through 3.13 on Linux, macOS and Windows, with x86_64 and arm64 builds for Linux and macOS and x86_64 only for Windows. Java is listed as 8-16+ on the same three systems.

How do I add Voyager to a Java or Scala build?

Add the com.spotify group, the voyager artifact and version 2.1.0 to your pom.xml as a dependency block. Scala builds use the matching line in build.sbt, and both snippets appear in the README.

Which nearest-neighbour algorithm does Voyager use?

HNSW, taken from the open-source hnswlib package and extended with added features for convenience and speed. The library works over an in-memory collection of vectors and calls itself approximate rather than exact.

Does the README show how to build an index or run a query?

No. It covers installation, the platform table and the licence line, then points to the separate Python and Java pages of the documentation site at spotify.github.io/voyager/. No index construction or query example appears on the page.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. spotify/voyager 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/spotify-voyager.svg)](https://hysenlabs.com/projects/spotify-voyager)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/spotify-voyager.svg)](https://hysenlabs.com/projects/spotify-voyager)

Was this useful?