Annoy

Approximate Nearest Neighbor (ANN) search library by Spotify — disk-based random projection tree index for fast similarity search. Annoy features: AnnoyIndex.build() for index construction, get_nns_by_vector()/get_nns_by_item() for queries, save()/load() for memory-mapped file indexes, n_trees parameter for accuracy/build-time trade-off, search_k for query-time recall control, on_disk_build() for large indexes that don't fit in RAM, angular/euclidean/manhattan/hamming/dot distance metrics, and read-only memory-mapped access (multiple processes share one index file). Designed for memory-efficient read-only serving of pre-built indexes.

Evaluated Mar 06, 2026 (0d ago) v1.17.x
Homepage ↗ Repo ↗ AI & Machine Learning python annoy spotify ann vector-search embeddings approximate-nearest-neighbor memory-mapped
⚙ Agent Friendliness
61
/ 100
Can an agent use this?
🔒 Security
91
/ 100
Is it safe for agents?
⚡ Reliability
81
/ 100
Does it work consistently?

Score Breakdown

⚙ Agent Friendliness

MCP Quality
--
Documentation
78
Error Messages
68
Auth Simplicity
98
Rate Limits
98

🔒 Security

TLS Enforcement
92
Auth Strength
92
Scope Granularity
90
Dep. Hygiene
85
Secret Handling
92

Local disk-based library — no network calls. Index files on disk may contain sensitive embeddings — apply filesystem permissions. Memory-mapped files visible to all processes running as same user.

⚡ Reliability

Uptime/SLA
82
Version Stability
85
Breaking Changes
85
Error Recovery
72
AF Security Reliability

Best When

Serving pre-built read-only vector indexes from disk across multiple processes — Annoy's memory-mapped files enable instant index loading and multi-process sharing without copying, ideal for production recommendation systems with static embeddings.

Avoid When

You need dynamic insertions (use hnswlib), very high dimensions, or GPU acceleration (use FAISS).

Use Cases

  • Agent similarity search with disk index — from annoy import AnnoyIndex; f = 128; t = AnnoyIndex(f, 'angular'); t.on_disk_build('index.ann'); [t.add_item(i, vec) for i, vec in enumerate(embeddings)]; t.build(50); t.load('index.ann'); nns, dists = t.get_nns_by_vector(query, 10, include_distances=True) — build and serve large index from disk without loading to RAM; agent serves 10M+ vector index on low-memory machine
  • Agent music/content recommendation — t = AnnoyIndex(64, 'angular'); t.load('tracks.ann'); similar_tracks = t.get_nns_by_item(track_id, 20) — find 20 most similar tracks by item ID without query vector; agent recommendation system uses pre-built Annoy index loaded at startup for sub-millisecond lookups
  • Agent multi-process index sharing — t.load('shared.ann', prefault=False) — memory-mapped index shared between worker processes without copying; agent scales to multiple parallel workers reading same index file; no inter-process coordination needed for read-only queries
  • Agent incremental index building — t.on_disk_build('large.ann'); for batch in batches: [t.add_item(i, v) for i, v in batch]; t.build(10) — build large index that exceeds RAM by writing directly to disk during construction; agent builds billion-vector index on 16GB RAM machine
  • Agent offline index precomputation — t = AnnoyIndex(384, 'angular'); t.add_items(all_embeddings); t.build(n_trees=100); t.save('production.ann') — offline build with high n_trees for maximum recall; agent deploys pre-built index file to production; load() is instant (memory-mapped)

Not For

  • Dynamic updates — Annoy indexes are immutable once built; adding items requires rebuilding entire index; use hnswlib for dynamic insertions
  • High-dimensional vectors (>500 dims) — random projection trees degrade at very high dimensions; use FAISS for high-dimensional vectors
  • GPU acceleration — Annoy is CPU-only; for GPU vector search use FAISS with GPU support

Interface

REST API
No
GraphQL
No
gRPC
No
MCP Server
No
SDK
Yes
Webhooks
No

Authentication

Methods: none
OAuth: No Scopes: No

No auth — local file-based index library.

Pricing

Model: open_source
Free tier: Yes
Requires CC: No

Annoy is Apache 2.0 licensed by Spotify. Free for all use.

Agent Metadata

Pagination
none
Idempotent
Full
Retry Guidance
Not documented

Known Gotchas

  • Index is immutable after build — t.build(50) freezes the index; t.add_item() after build raises Exception; agent code must add ALL items before calling build(); if items need to be added dynamically, use hnswlib instead; Annoy is build-once-serve-many
  • on_disk_build vs add_items memory difference — AnnoyIndex(f, 'angular') with add_items loads all vectors in RAM during build; use t.on_disk_build('file.ann') BEFORE add_item() calls to write directly to disk; agent building indexes exceeding available RAM must call on_disk_build() first
  • load() is zero-copy memory-mapped — t.load('index.ann') returns instantly but doesn't read into RAM; first query triggers actual disk reads; agent benchmark showing fast load but slow first queries should call t.load('index.ann', prefault=True) to pre-load into page cache on warm-up
  • get_nns_by_vector dimensions must match exactly — query vector must have exactly f dimensions (set at AnnoyIndex(f, ...)); wrong dimension raises ValueError with no detail about expected vs actual; agent code must verify len(query_vector) == f before calling get_nns_by_vector()
  • search_k controls recall-speed trade-off at query time — t.get_nns_by_vector(query, 10) uses default search_k=-1 (n_trees * k); set search_k explicitly: t.get_nns_by_vector(query, 10, search_k=5000) for higher recall at cost of speed; agent must tune search_k for production recall requirements
  • Angular distance is cosine not dot product — AnnoyIndex(f, 'angular') computes angular distance (based on cosine similarity) not inner product; agent code comparing Annoy distances to raw dot products will see different values; pre-normalize vectors for true cosine similarity comparison

Alternatives

Full Evaluation Report

Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for Annoy.

$99

Scores are editorial opinions as of 2026-03-06.

5173
Packages Evaluated
26151
Need Evaluation
173
Need Re-evaluation
Community Powered