Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

approximate nearest neighbour (ANN)
A search that checks only part of the index, so it is fast but may miss some of the true closest matches.
collection
A named group of vectors that share one configuration and are searched together.
cosine similarity
The dot product of two unit-length arrows, from 1 when they point the same way to -1 when they oppose.
dot product
Multiply matching numbers in two lists and add the results; it grows with both length and agreement.
embedding
A list of numbers that places a piece of text in a space where similar meanings sit close together.
embedding model
The trained program that turns text into vectors, with one fixed output width.
hybrid search
Running a word-matching search and a meaning-based search together, then combining their ranked lists into one.
index
A structure built ahead of time so the database can find nearby items without comparing against every one.
magnitude
The length of a vector, found by squaring its numbers, adding them and taking the square root.
metadata filter
A rule that keeps only the items whose stored facts, such as date or owner, match before or during the search.
model card
A short document describing a trained system: its data, its scores and its known limits.
normalised vector
A vector divided by its own length, so it has length one and only direction remains.
quantisation
Storing each number with less precision, which shrinks memory and usually costs a little accuracy.
recall
The share of the truly closest items that a search actually returned.
reranking
Scoring a short list of results again with a slower, more careful method and putting the best first.
similarity function
A rule that scores two vectors and returns a number saying how alike they are.
top-k
The shortlist a search returns: its best few results, cut off at a number chosen in advance.
training loss
The average error an embedding model makes on the text pairs it is trained to match.
unit length
A vector whose magnitude is exactly 1, which makes a dot product read as pure agreement.
vector
An ordered list of numbers, where each position is one measured property.

Vector databases from the ground up

What a vector index is

A vector index answers one question fast: which stored vectors are nearest to this one? Everything else a vector database does is storage, filtering and operations around that answer.

Part 1 of 10

Intermediate14 min readBack to Courses

A search problem in disguise

An embedding turns a piece of text, an image or a user into a list of numbers. Once all of it is a list of numbers, “find something similar” becomes “find the points closest to this point”. The index is the data structure that answers that question without comparing the query to every stored item. The whole discipline is about doing that comparison cheaply without losing the answer.

That is the whole trick, and it is worth being precise about it. The index does not read your documents and does not know what a refund is. It holds coordinates and it is very good at geometry. Meaning entered the system earlier, when the embedding model turned text into a position. Every quality problem you later blame on the database probably started there.

The useful mental model is a filing cabinet organised by meaning rather than by name. You do not ask for the folder called “refunds”; you hand over a description and the cabinet returns the folders whose descriptions sit closest to it. The cabinet is fast because it never reads the folders, only their labels. That is also why it can be confidently wrong.

The index is one part of the database

A vector database is an index plus everything a database needs: durable storage, a write-ahead log, metadata, a query planner, replication, backups and access control. The index decides how fast a search is; the rest decides whether the data is still there tomorrow. A benchmark that measures only queries per second is measuring the easy half.

Most disappointment with vector databases comes from confusing the two. An index that returns neighbours in two milliseconds is not a database, and a database with a slow index is not a fast one. Before comparing products, ask which half your problem belongs to. If the complaint is latency, it is the index. If it is a lost write or a leaked row, no index will save you.

The index, without the database

import faiss
import numpy as np

index = faiss.IndexFlatIP(384)
index.add(np.array(vectors, dtype="float32"))

scores, ids = index.search(np.array([query], dtype="float32"), k=5)
for score, item_id in zip(scores[0], ids[0]):
    print(round(float(score), 3), item_id)

A flat index in twenty lines

Run the search, then add a sixth document about shipping and confirm it can enter the top three. Change k to 1 and to 10 and watch the edges.

Output
Click "Run" to execute your code

Ids, not text

An index stores vectors and identifiers, never the payload (the text and other fields). Search returns ids, and your application joins them to the rows that hold the text, the tenant and the permissions. That join is where most of the interesting bugs live. A deleted row can still have a vector in the index. A vector can outlive the text it was built from, or a filter can run on the index but not on the join. Treat the join as a first-class step with its own tests, not as a line of glue.

Keeping the payload out of the index is not laziness. It lets the index be small and the payload transactional (saved as one reliable unit). It also makes it clear which of the two is the source of truth when they disagree. The index is a cache of nearness; the row is the record. Once you say that out loud, the recovery path for a corrupt index is to rebuild it from the rows.

Normalise the vectors before you build an inner-product index, or use a metric that normalises for you. Mixing normalised and unnormalised vectors in one index produces scores that look fine and rankings that are wrong.

The interface is four calls

Add a vector with an id. Search for the k nearest to a query. Delete an id. Persist and reload. Every vector database, from a ten-line Python class to a distributed service, exposes those four calls under different names. The names are the least interesting thing about them. What differs is the cost of each call and the failure mode when it goes wrong.

Everything else — the graph, the partitions, the replicas — is an implementation detail (a choice made inside the software) behind them. Learn the four calls and the operating questions that follow, and a new product becomes a mapping exercise rather than a new field. The questions are always the same. How exact is the search, what does an update cost, what happens when a node dies, and how do you know the answers are still good?

That is also the right order for learning the rest of this course. Each chapter takes one of the four calls and asks what it costs at scale. How is the index built, how does a filter change the search, and what does a delete leave behind? How is the whole thing measured when it is too large for one machine? By the end, the four calls will look like four questions about failure.

The index knows ids, not meaning

Search, delete id 3, and search again. Notice that the index never returned text: the payload dictionary did, and the two can drift.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What does a vector index store?