FAISS
FAISS is Meta's open-source library for efficient similarity search and clustering of dense vectors, with CPU and GPU indexes. Learn index types and trade-offs.
Overview
FAISS, short for Facebook AI Similarity Search, is an open-source library from Meta for searching and clustering dense vectors. You give it a large set of embeddings, and it answers one question very quickly: which stored vectors are closest to this query vector? It does this on CPUs, and optionally on GPUs, using a family of index structures that trade speed, memory and accuracy against each other.
FAISS is a library, not a database. It runs inside your own process. It has no server, no user accounts, no replication and no query language. That is a deliberate choice. It lets FAISS focus on the hard numerical part of vector search and leave storage, access control and filtering to the system around it.
Think of FAISS as a high-performance engine sold without a car. A carmaker can drop it into a sports car, a lorry or a boat. In the same way, search systems, research code and some vector databases embed FAISS, or reimplement its ideas, and build the rest of the vehicle themselves.
What it is
FAISS is a C++ library with optional Python wrappers. Its core idea is the index: an object that stores vectors in some structure and supports add and search. Different index classes implement different search strategies.
| Part | What it does | Main trade-off |
|---|---|---|
| Flat indexes | Compare the query with every stored vector | Exact results, but cost grows linearly with data size |
| Inverted file (IVF) | Group vectors into clusters and search only the closest clusters | Much faster, small loss of recall |
| Quantizers (scalar, product, additive) | Compress each vector into a short code | Far less memory, lower precision |
| Graph indexes (HNSW, NSG) | Walk a neighbour graph towards the query | Fast and accurate, but uses more memory |
| Binary indexes | Search bit vectors with Hamming distance | Very compact, needs binary embeddings |
| GPU indexes | Run search and training on NVIDIA or AMD GPUs | Very high throughput, limited by GPU memory |
| Index factory | Builds composite indexes from a short text string | Convenient, but hides details |
The library mainly supports two distance measures: Euclidean (L2) distance and inner product. Cosine similarity is handled by normalising vectors and then using inner product. Other metrics have more limited support.
Where it came from
FAISS was developed at Facebook AI Research (FAIR), now part of Meta. The original authors were Hervé Jégou, Matthijs Douze and Jeff Johnson. It was released as open source in February 2017 and is published under the MIT licence.
The library grew out of years of research on compact codes for nearest-neighbour search. Jégou and Douze had earlier co-authored the influential product quantization paper (with Cordelia Schmid, published in 2011), which showed how to compress vectors into short codes while still estimating distances accurately. FAISS turned that line of work into production-quality code.
Key milestones:
- 2017: open-source release, together with the paper "Billion-scale similarity search with GPUs" by Johnson, Douze and Jégou, which described the GPU implementation. It later appeared in IEEE Transactions on Big Data.
- Later years: graph indexes such as HNSW and NSG, fast-scan product quantization, additive quantizers and neural quantization (QINCo) were added.
- 2024: the overview paper "The Faiss library" by Douze and colleagues described the design and the trade-offs in one place.
- Recent releases: optional NVIDIA cuVS backends for GPU indexes, alongside support for AMD ROCm.
How it works
1. Choose an index
You pick a structure that fits your data size and budget. The index factory lets you describe a composite index in a string such as "IVF4096,PQ32", which means 4,096 clusters with 32-byte product-quantized codes.
2. Train, if the index needs it
Some indexes learn from data. IVF runs k-means to find cluster centres. Product quantization learns small codebooks for each slice of the vector. Training uses a representative sample, not necessarily the full dataset. Flat and HNSW indexes need no training.
3. Add vectors
You add vectors in batches. For IVF, each vector is assigned to its nearest centre and stored in that cluster's list. For quantized indexes, the vector is encoded into a short code and the original floats are dropped. Each vector gets an integer id, either sequential or supplied by you through an id map.
4. Search
A query returns two arrays: distances and ids of the k nearest results. For IVF, the parameter nprobe sets how many clusters to visit. More probes mean higher recall and slower queries. For HNSW, efSearch plays a similar role.
5. Persist and serve
Indexes can be saved to and loaded from disk. Serving, sharding and concurrent updates are the job of the surrounding application.
import faiss
index = faiss.index_factory(768, "IVF4096,PQ32")
index.train(sample_vectors) # float32 array, shape (n, 768)
index.add(all_vectors)
faiss.extract_index_ivf(index).nprobe = 16
distances, ids = index.search(query_vectors, 10)
Key concepts and terms
| Term | Meaning |
|---|---|
| k-NN search | Finding the k stored vectors closest to a query |
| Approximate nearest neighbour (ANN) | Search that accepts small errors in exchange for speed |
| Recall@k | Share of true nearest neighbours found in the top k results |
| IVF | Inverted file: vectors grouped by nearest cluster centre |
| nlist | Number of clusters in an IVF index |
| nprobe | Number of clusters scanned per query |
| Product quantization (PQ) | Compression that splits a vector into parts and encodes each with a small codebook |
| HNSW | Hierarchical navigable small world graph index |
| Index factory | String syntax for building composite indexes |
| Training | Learning centres or codebooks from sample data |
| Inner product | Dot product; equals cosine similarity for normalised vectors |
A worked example
This is an illustrative scenario, not a report of a real deployment.
A media archive holds 50 million image embeddings of 512 dimensions in float32. Stored raw, that is 50,000,000 × 512 × 4 bytes, about 102 GB. The team wants to find near-duplicate images on a single server with 64 GB of RAM.
- They first build a flat index on a 1 million-vector sample. This gives exact neighbours, which they keep as ground truth.
- They choose
"IVF16384,PQ64". Each vector becomes a 64-byte code, so the codes take about 3.2 GB, plus list overhead. - They train on 1 million sampled vectors, then add all 50 million in batches.
- On a set of 10,000 test queries, they measure recall@10 against the flat ground truth at several
nprobevalues. Recall climbs asnproberises from 8 to 64, while query time grows roughly in proportion. - They pick the smallest
nprobethat meets their recall target, then re-rank the top 100 candidates with exact distances from vectors stored on disk.
Strengths and limitations
Strengths:
- Very fast exact and approximate search on CPU and GPU.
- Wide choice of indexes and compression methods in one library.
- Composable building blocks and an index factory for experiments.
- Permissive MIT licence.
Limitations:
- Not a database: no built-in server, replication, sharding or access control.
- Metadata filtering is limited compared with vector databases; most filtering must be designed around it.
- Deleting and updating vectors is awkward for many index types.
- Choosing and tuning indexes needs some expertise.
- GPU indexes are bounded by GPU memory and support fewer index types than CPU.
How it compares with alternatives
| Option | Type | Best for | Compared with FAISS |
|---|---|---|---|
| FAISS | Library | Embedded search, batch jobs, research | Baseline |
| ScaNN | Library | Inner-product search on CPU | Strong speed for MIPS, narrower index choice |
| hnswlib / HNSW | Algorithm and library | Simple in-memory graph search | Simpler, but graph-only |
| pgvector | Postgres extension | Vectors next to relational data | Full SQL and transactions, less raw speed |
| Milvus or Qdrant | Vector database | Production services with filtering | Adds persistence, APIs and scaling |
Practical guidance and best practices
- Build a flat index on a sample first. It gives you ground truth for measuring recall.
- Normalise vectors and use inner product if your embedding model expects cosine similarity.
- Under about a million vectors, flat or HNSW is often enough; reach for IVF and PQ as memory becomes the limit.
- Set the number of IVF clusters in proportion to the square root of the dataset size as a starting point, then measure.
- Train quantizers on data that looks like what you will store, not on a different domain.
- Tune
nprobeorefSearchagainst a recall target, and record the chosen values. - Re-rank a short list of candidates with exact distances when precision matters.
- Plan for updates: rebuild periodically or keep a small flat "fresh" index alongside the main one.
Common mistakes
- Treating FAISS as a database and expecting persistence, filtering or access control.
- Mixing cosine and inner product without normalising vectors.
- Training quantizers on too few vectors, which produces poor codebooks.
- Reporting speed without reporting recall.
- Leaving
nprobeat its default and concluding that IVF is inaccurate. - Forgetting that float64 arrays must be converted to float32 before use.
Frequently asked questions
Is FAISS a database?
No. FAISS is a library that runs inside your program. It indexes and searches vectors, but it does not provide a server, concurrent writes, sharding, replication or access control. Vector databases add those features, sometimes using FAISS or similar algorithms underneath.
Does FAISS support GPUs?
Yes. Many index types have GPU versions that use NVIDIA CUDA, and AMD ROCm is also supported. Recent versions can optionally use NVIDIA cuVS implementations. GPU search is very fast, but the index must fit in GPU memory, and not every CPU index has a GPU counterpart.
Which index should I start with?
Start with a flat index for small data or to create ground truth. Move to HNSW when you need fast queries and have enough RAM. Move to IVF with product quantization when the raw vectors no longer fit in memory. Always confirm the choice by measuring recall on your own queries.
Can FAISS filter by metadata?
Only in limited ways. Some indexes accept an id selector that restricts search to a subset of ids. Rich filtering on attributes such as date or category is usually done outside FAISS, or by choosing a vector database designed for it.
How do I install FAISS?
The project publishes packages through conda, including CPU and GPU builds. You can also build from source with CMake, with a BLAS library as the only required dependency. Community-built wheels exist on PyPI, but the official instructions focus on conda and source builds.
Glossary
- Embedding: a vector of numbers that represents the meaning of an item.
- Codebook: a small set of representative vectors used for quantization.
- Centroid: the centre of a cluster found by k-means.
- Quantization: replacing exact values with a short code from a codebook.
- Brute-force search: comparing a query with every stored vector.
- Re-ranking: rescoring a short candidate list with exact distances.
- BLAS: a standard library of fast linear algebra routines.
Summary
FAISS is Meta's open-source library for fast similarity search and clustering of dense vectors. It offers flat, inverted-file, quantized and graph indexes on CPU and GPU, all built around a trade-off between speed, memory and accuracy. It is not a database, so persistence, filtering and serving are your responsibility. Use it when you need raw performance inside your own code or batch jobs, start from exact ground truth, and tune parameters by measuring recall on your own data. For context on where it fits, see hybrid search and k-nearest neighbours.
Related
It belongs to Vector databases in my stack, under Generative AI and LLMs. Others in the same group: