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
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
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
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.
Related
- Row Level Security (RLS) explained with examples
- Add Google and GitHub sign-in with supabase-js
- Passwordless magic link login
- Realtime database subscriptions
- Quickstart
- supabase-js client docs
Updated 2026-10-23.