ByeBuy.ai
BUILD YOUR ESCAPE ROUTE · ✦ CURSOR · HOST IT · ◫ SUPABASE · CONNECT IT · ↯ RELAY · BUILD YOUR ESCAPE ROUTE · ✦ CURSOR · HOST IT · ◫ SUPABASE · CONNECT IT · ↯ RELAY ·
← BYEBUY NOTES

September 12, 2026

VECTOR SEARCH IN POSTGRES: USEFUL WHEN YOU ALREADY HAVE PRODUCT DATA

Vector Search in Postgres: Useful When You Already Have Product Data

In Lesson 22.1 you learned what embeddings are for; in Lesson 22.2 you split documents into labeled chunks and traced the retrieve-and-filter pipeline. One question remains: where does all of this *live*? This lesson gives the smallest serious answer — the database you already met in Classes 20 and 21, extended with one new kind of column.

Vectors are a column, not a replacement

Bridge from Class 20 first: a database is the part of your app that remembers. Postgres already remembers your companies, filings, reports, users, and permissions. Vector search does not replace any of that — it adds one more column type alongside title, date, source, and ID.

A chunk record is mostly ordinary: title, section, source URL, owner, updated-at timestamp, visibility flag, product ID. The only new arrival is the embedding — the list of numbers from Lesson 22.1, stored per chunk. SQL filters keep doing what they do best (product, rights, time, language), and a similarity operation ranks the surviving rows by meaning. Records, filters, and semantic ranking in one system, one query path, one access-control story.

That is the durable decision hiding inside this lesson: choose the smallest storage architecture that meets the actual retrieval need. For most first products, that is the Postgres system you already have.

pgvector: similarity search inside Postgres

The tool that makes this concrete is pgvector, the open-source Postgres extension that stores vectors and performs similarity search. It adds a vector column type and nearest-neighbor lookup, so a query can ask "find the chunks whose embeddings sit closest to this question embedding" — optionally combined in the same query with WHERE visibility = … AND product_id = ….

Keep vendor proportion right: pgvector is infrastructure, not intelligence. A vector index improves retrieval; it does not decide truth, check currency, enforce intent, or replace source review. Every boundary from Lessons 22.1 and 22.2 still applies — similarity proposes, filters and freshness dispose.

How embeddings get made is a separate step. An embedding model — for example, one described in the OpenAI embeddings guide — converts each chunk (and later each question) into its number list. Remember that guide's core point: the embedding is a numeric representation for similarity, not a factual answer. Your pipeline calls the model at ingest time and at query time, then stores and compares the results in Postgres.

A conceptual table

You do not need to install anything in this lesson. You need to be able to *sketch* the table and read it back. Here is the shape:

ColumnType (conceptual)Purpose
idstable IDOne row per chunk; stable even when titles change
document_titletextHuman-readable source, e.g. "Password & login help"
sectiontextPosition inside the document, e.g. "Resetting your password"
chunk_texttextThe actual retrievable passage
embeddingvectorThe chunk's number list, made by the embedding model
source_urltextLink to the real evidence the answer must show
updated_attimestampCurrency check: is this procedure still current?
visibilitytext / access flagPermission check: who may retrieve this row?
product_idID → productsScope check: which product does this chunk belong to?

A retrieval query then reads naturally: *among chunks where product_id matches this user, visibility permits this user, and updated_at is current — return the K rows whose embedding sits nearest the question embedding, with their titles and source URLs attached.*

For Sonariq, the same table holds research sections: document_title names the report, section names the analysis block, product_id scopes to the covered company, and source_url points at the filing the section was drawn from. The pattern transfers to support assistants, handbooks, and operations copilots unchanged.

Minimal DDL sketch

Copy this shape into your DATABASE-SKETCH.md and adapt the names. Vectors are one column; everything else is ordinary Postgres you already know from Classes 20–21.

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id          text PRIMARY KEY,
  title       text NOT NULL,
  source_url  text NOT NULL,
  owner       text NOT NULL,
  updated_at  timestamptz NOT NULL,
  visibility  text NOT NULL          -- e.g. 'public' | 'internal'
);

CREATE TABLE chunks (
  id             text PRIMARY KEY,
  document_id    text REFERENCES documents(id),
  section        text NOT NULL,
  position       int  NOT NULL,       -- 1 of N, 2 of N …
  chunk_text     text NOT NULL,
  embedding      vector(1536) NOT NULL,
  source_url     text NOT NULL,        -- exact section link
  updated_at     timestamptz NOT NULL,
  visibility     text NOT NULL,
  product_id     text NOT NULL         -- scope: which product/company
);
-- Retrieval: WHERE visibility + product_id + updated_at first,
-- then ORDER BY embedding <-> :question_embedding LIMIT 5;

Stay-on-Postgres checklist

Stay on one Postgres (with pgvector) while all of these hold. Leave only on measured evidence:

  • [ ] Chunks number in the hundreds or low thousands — not millions.
  • [ ] Query volume fits one managed instance (Supabase / Neon from Class 20) with headroom.
  • [ ] Latency budget is met without specialized indexing work.
  • [ ] No measured retrieval failures traceable to the store itself (vs. chunking, filters, or prompts).
  • [ ] Permissions still enforceable in one WHERE clause per query.

If a box stops holding, write the number down — chunk count, p95 latency, failed-query log — and let that number, not fashion, justify the second system.

Why one Postgres is appealing — and when to leave it

The one-Postgres appeal is operational simplicity. A small application's normal records, access filters, and vector similarity live in one system: one backup story, one permission story, one query language the builder already learned in Class 21, one managed provider (Supabase or Neon from Class 20) to operate. There is no second database to sync, secure, and pay for while the corpus is small and the team is learning.

A dedicated vector product — a standalone vector database or managed retrieval service — may become appropriate later, on evidence, not fashion:

  • Scale: millions of chunks, high query volume, or latency budgets one Postgres instance stops meeting.
  • Retrieval workload: hybrid ranking, large-scale filtering, or multitenant throughput that needs specialized indexing and operations.
  • Team evidence: measured retrieval failures, growth numbers, or operational requirements — not a conference talk — saying the current system is the bottleneck.

Until that evidence exists, a second system is a second bill, a second sync pipeline, and a second permission boundary to get wrong. Start with Postgres plus pgvector; graduate when measurements say so.

Practical exercise: the retrieval section of your sketch

1. Open the DATABASE-SKETCH.md you started in Class 20 (or start one now with a single table for your product's documents). 2. Add a retrieval section answering three questions:

  • What gets chunked? Name the document types (help articles, policies, research sections) and your chunk boundary rule from Lesson 22.2.
  • Which filter applies first? Name the one metadata filter that must gate retrieval before similarity — usually visibility, product_id, or a freshness cutoff — and say why it comes first for *your* product.
  • What evidence would prove semantic retrieval is needed at all? Write down the test: five real user phrasings (from Lesson 22.1's exercise) that keyword search fails but meaning-level retrieval should catch.

3. End with an explicit non-decision: "We will stay on one Postgres until [concrete metric], and we will not add a dedicated vector product before then."

Finish line: a retrieval section in DATABASE-SKETCH.md naming chunked types, the first filter, the need-evidence test, and the stay-on-Postgres threshold.

Verify: re-read your filter answer against Lesson 22.2's list (product, rights, time, language, scope). If your "first filter" is similarity ranking rather than a metadata gate, rewrite it — eligibility comes before nearness.

Common failure mode: adding a dedicated vector database "for scale" with ten documents and no users. Scale is a measurement, not a mood. One Postgres, honestly filtered, beats two systems, hopefully synced.

Check your understanding

1. What does the embedding column store, and what do the other columns do? 2. What is pgvector, and what does it *not* do? 3. Why is one Postgres appealing for a small application's first retrieval system? 4. Name three kinds of evidence that would justify a dedicated vector product later. 5. What is the durable architecture decision in one sentence?

ARTICLE DISCUSSION

JOIN THE
CONVERSATION.

0 COMMENTS

BYEBUY ACCOUNT ACCESS

Sign in

Use your account to save routes and make the catalogue yours.

Enter your email and we’ll send a secure sign-in link and code.

NEW ROUTES ADDED WEEKLY · 9,235 CATALOGUE ENTRIES · BUILD · DEPLOY · QUERY · STACK · SAY BYE TO BUY · NEW ROUTES ADDED WEEKLY · 9,235 CATALOGUE ENTRIES · BUILD · DEPLOY · QUERY · STACK · SAY BYE TO BUY ·