The full answer
An embedding model turns a piece of text into a list of numbers (a vector) so that texts with similar meaning land close together. Vector search embeds the question the same way and finds the stored vectors nearest to it, usually by cosine similarity. For more than a few hundred thousand vectors you use an approximate index. HNSW is the usual choice for its speed and recall. IVF builds faster and uses less memory but needs tuning and data to train on.
Embeddings in practice
- Use the same model for documents and questions. Vectors from different models cannot be compared.
- The vector length (for example 1,024 numbers) fixes storage size. Some models allow shorter vectors at a small cost in quality.
- Changing the model means re-embedding everything, so record which model made each vector.
- Some models expect different input types for queries and documents. Follow the model's guidance.
Exact vs approximate search
Exact search compares the question with every vector. It has perfect recall and is fine up to perhaps a few hundred thousand vectors. pgvector does this by default. Beyond that, approximate nearest neighbor search trades a little recall for a lot of speed.
HNSW vs IVF (as pgvector describes them)
| HNSW | IVFFlat | |
|---|---|---|
| How it works | A layered graph; search hops towards the nearest neighbours | Clusters vectors into lists; search checks the nearest few lists |
| Query speed vs recall | Better | Worse |
| Build time and memory | Slower, more | Faster, less |
| Needs data first | No, can be built on an empty table | Yes, the lists are trained on existing rows |
| Tuning at query time | hnsw.ef_search (default 40): higher means better recall, slower | ivfflat.probes (default 1): more lists means better recall, slower |
Distance
pgvector's operators are <-> (Euclidean), <=> (cosine distance) and <#> (negative inner product). Use the metric the embedding model was trained for. For normalised vectors, cosine and inner product rank the same way.
Choosing a store
If your data already lives in Postgres, pgvector keeps vectors next to the rows, with transactions, joins and permission filters in one query. A dedicated vector database earns its place at very large scale, or when you need built-in hybrid search and multi-tenancy.
What to measure
Recall@k against exact search on a sample of queries, and query latency at your real data size. Then tune ef_search or probes until recall is good enough at an acceptable latency. Remember that vector search finds similar text, not correct text, which is why hybrid search and reranking come next.
Last updated 16 October 2026
Sources