How-to guides

Build semantic search with pgvector on Postgres

Every Da8a project includes pgvector, so you can keep embeddings next to the rows they describe and search by meaning with plain SQL.

Create the table

SQL editor
create extension if not exists vector;
create table documents (
  id bigint generated always as identity primary key,
  content text not null,
  embedding vector(1536)
);
create index on documents using hnsw (embedding vector_cosine_ops);

A search function

SQL editor
create function match_documents(query vector(1536), match_count int default 5)
returns table (id bigint, content text, similarity float)
language sql stable as $$
  select id, content, 1 - (embedding <=> query) as similarity
  from documents
  order by embedding <=> query
  limit match_count;
$$;

Create embeddings in an edge function

Keep your embedding provider’s API key in a function secret, embed the text, and insert the row with a service-key client. See edge functions.

Search from the client

search.ts
const { data } = await supabase.rpc('match_documents', {
  query: embedding, match_count: 5,
})

Questions

Which index should I use?

HNSW is a good default for most apps; IVFFlat builds faster on very large tables.

Do RLS policies apply?

Yes, to the table. Functions run with the caller’s permissions unless declared security definer.

Updated 2026-10-23.