What you'll learn: what embeddings would add to the capstone's BM25 keyword search and what they would not, how to size and index a vector table in PostgreSQL with pgvector, which settings trade recall for speed, why filters behave differently on approximate indexes, and how to measure a change before you trust it. This is a design lesson. Nothing in it ran: no embedding model, no PostgreSQL and no pgvector were used in this course's environment, and every code block is pseudocode.
At a glance
Figure 1. Where a vector index would sit next to the keyword index
How to read this: the solid path is the capstone as built; the dashed red edge is the design this lesson discusses, and both indexes return chunk ids into the same store.
- Embeddings help when the user's words differ from the document's words. They can hurt on exact identifiers.
- The capstone has 174 chunks, so an exact scan is cheap and no approximate index is needed.
- An approximate index trades recall for speed, and the trade has settings you tune against exact search.
- With approximate indexes, a filter runs after the index scan, so a restrictive filter can return fewer rows than you asked for.
- Add the vector path only after a measured miss says wording is the cause, and measure the change per question.
Scenario
Composite scenario, not a real company. Lumen Industrial Supply's sales engineers search product documents with the copilot. Keyword search finds "LUM-GW-200 serial ports" at once. A new hire types "gadget to watch machine tremors" and gets controller manuals, because none of those words appear in the datasheets. The head of sales asks for "AI search". The FDE must say what that would involve, what it would cost to run, and how to tell whether it worked, without building it first. Figures are illustrative.
What you will be able to do
- State which kinds of retrieval failure embeddings can fix and which they cannot.
- Size a vector table from the number of chunks and the embedding dimension, and check it against the index limits.
- Choose between exact search, HNSW and IVFFlat, and name the settings that trade recall for speed.
- Explain why filtered queries on approximate indexes can return too few rows and list the documented remedies.
- Write a measurement plan that compares approximate search with exact search and the new ranking with the old, per question.
Prerequisites
- Keyword, vector and hybrid search for RAG: BM25 in the capstone, where it fails, and the reciprocal rank fusion code that combines two rankings. This lesson does not repeat it.
- Metadata filters and tenant-aware access control: why the capstone filters inside the query.
- Evaluating retrieval and answers: per-question failure classes.
- Embeddings in theory and store choices are in Data and retrieval.
Core ideas
What embeddings add to keyword search
An embedding model turns a chunk of text into a list of numbers, a vector. Texts with similar meaning get nearby vectors, so a query can match a chunk that shares no words with it. That is the one thing keyword search cannot do. It is also not free: you pick a model, pay to run it on every chunk and every query, and store and index the vectors.
| Failure | Does a vector index help? | Why |
|---|---|---|
| Paraphrase: "machine tremors" vs "vibration" | Yes, in principle | meaning matches where words do not |
| Exact identifier: "LUM-GW-200" | Risk of making it worse | the Contextual Retrieval write-up says embeddings can miss crucial exact matches while BM25 handles unique identifiers |
| Superseded document cited | No | a metadata problem, fixed by a filter |
| Partner-only document shown | No | an access problem, fixed in the query |
| Wrong chunk size | No | chunking, not matching |
That is why the design keeps BM25 and adds vectors beside it, and fuses the two rankings. Reciprocal rank fusion is covered in the search lesson and its tested code is not repeated here.
Predict first. The capstone's golden set has two misses where an expected document sits low in the plain BM25 ranking: q01 (the datasheet is at document rank 14) and q07 (an FAQ at rank 6). Would you expect an embedding model to fix both? Decide, then open the answer.
Answer
Not safely. Both misses are about words that dominate the ranking: in q01 the OPC UA terms pull in compatibility notes ahead of the sensor datasheet. Whether an embedding model would rank the datasheet higher is an empirical question that nothing in this course ran. The honest design treats it as a hypothesis, measured on those two questions and on new paraphrase questions, not as a promise.
What you store
The vector table keeps the capstone's chunk ids and the metadata the filter needs, next to the vector. The column type needs the model's output dimension, so the model choice comes first and is recorded with the data. Vectors from two different models are not comparable, so changing the model means re-embedding every chunk.
Pseudocode. Nothing below was executed.
CREATE EXTENSION vector;
CREATE TABLE chunk_vectors (
chunk_ref text PRIMARY KEY, -- same ids as the capstone: "ds-vs-100#2"
visibility text NOT NULL, -- public or partner_only
status text NOT NULL, -- current or superseded
skus text[] NOT NULL,
model_id text NOT NULL, -- which embedding model produced the vector
embedding vector(1024) NOT NULL -- 1024 is an illustrative dimension
);
The pgvector README gives the storage cost: each vector takes 4 bytes per dimension plus 8 bytes, and each half-precision vector takes 2 bytes per dimension plus 8 (as of 2026-11-02, from the README). It also gives the limits for indexing: up to 2,000 dimensions for vector and up to 4,000 for halfvec.
| Case | Calculation | Result |
|---|---|---|
| The capstone: 174 chunks at 1,024 dimensions | 174 x (4 x 1,024 + 8) bytes | 714,096 bytes, about 0.68 MiB |
| A customer: 30,000 chunks, same dimension | 30,000 x 4,104 bytes | 123,120,000 bytes, about 117.4 MiB |
| The same, half precision | 30,000 x 2,056 bytes | 61,680,000 bytes, about 58.8 MiB |
| A 3,072-dimension model | 4 x 3,072 + 8 | 12,296 bytes per vector; too wide to index as vector |
These are vector bytes only. The index, the text and the metadata are extra, so measure the real table. The point of the arithmetic is to see in minutes that the capstone is tiny and a customer's corpus is still modest, which sets how much tuning is worth doing.
Exact search first, approximate when it is too slow
By default pgvector does exact nearest-neighbour search, which the README says gives perfect recall. At 174 chunks, scanning every vector per query is trivial, so the capstone would need no vector index at all. An approximate index becomes worth its cost when the scan is too slow for your latency budget. The README says it plainly: an approximate index trades some recall for speed, and you will see different results for queries after adding one.
Figure 2. Choosing an index
How to read this: the first question is whether you need an approximate index at all; the second chooses between two with different costs.
The settings that move recall and latency
The README describes both index types and the knobs below. Defaults are as of 2026-11-02.