Watch the port. Copying the string from the wrong tab is the most common “it works locally, not in prod” bug.
Enable pgvector
Two ways, pick either.
SQL editor (project → SQL Editor → New query):
create extension if not exists vector;
Dashboard: Database → Extensions → search vector → toggle on.
Verify:
select extname, extversion from pg_extension where extname = 'vector';
Add a vector column
-- 1536 = output width of OpenAI text-embedding-3-small.-- The number must match your embedding model exactly.alter table todos add column if not exists embedding vector(1536);
Keep it nullable. Existing rows have no vector, and new rows are usually embedded just after insert.
Add an index only when you have tens of thousands of rows:
create index on todos using hnsw (embedding vector_cosine_ops);
HNSW is approximate — it trades recall for speed.
Notes / gotchas
Free projects pause after ~1 week of inactivity. Restore them from the dashboard.
The service_role key bypasses row level security. Server-side only, never in the browser.
Changing embedding model = changing the column width = re-embedding every row. Plan a backfill endpoint from day one.