vector extension is created at project provision time and used internally by ai.embeddings. You can use it for your own tables too: store embeddings in public.* and run vector similarity queries via PostgREST or direct SQL.
For most users, the typed Sources + Knowledge Bases surface is the right path — it manages chunking, embedding, indexing, RLS, billing, and retrieval reranking for you. Rolling your own pgvector tables is for cases where the typed surface doesn’t fit: custom embedding models, specific schema constraints, integration with non-Powabase pipelines.
This page covers the user-managed approach so you can choose the right tool for the job.
When to use which
| You want… | Use |
|---|---|
| RAG over uploaded documents | Sources + KB (/api/sources, /api/knowledge-bases) |
| Hybrid search (vector + BM25 + rerank) | KB search (/api/knowledge-bases/{id}/search) |
| Custom embedding model / non-text data (image embeddings, audio) | User-managed pgvector |
| Schema-coupled embeddings (“each row has its own embedding column”) | User-managed pgvector |
| Integration with an external indexing pipeline | User-managed pgvector |
| Per-user RLS that the typed KB surface doesn’t yet support | User-managed pgvector |
vector_search calls (see Billing model). For high-volume retrieval against a fixed corpus, user-managed can be cheaper at the cost of more setup.
The basic shape
A user-managed embeddings table is just a regular table with avector(N) column where N is your embedding dimension.
- OpenAI
text-embedding-3-small: 1536 - OpenAI
text-embedding-3-large: 3072 - Cohere
embed-english-v3.0: 1024 - Voyage
voyage-3-large: 1024 - BGE M3: 1024
expected N dimensions, not M.
Indexing for fast search
Avector column without an index does a sequential scan for every search — fine for thousands of rows, slow above tens of thousands. Two index types: HNSW and IVFFlat.
HNSW (Hierarchical Navigable Small World) is what Powabase uses internally and what most production setups want. Faster searches, slower builds, no parameter tuning at query time:
embedding::vector(1536) is what pgvector wants for HNSW with explicit dimension typing — without it the index may not be picked up at query time.
vector_cosine_ops is the distance operator class:
vector_cosine_ops— cosine distance (most common for text embeddings)vector_l2_ops— Euclidean distancevector_ip_ops— inner product (negative dot product)
lists tuning:
lists is roughly rows / 1000 for the rule-of-thumb default. Use HNSW unless you have a specific reason — it’s strictly better for most workloads.
Inserting embeddings
You compute the embedding in your application code (calling OpenAI, Cohere, etc.) and insert via PostgREST or SQL:embedding column expects a JSON number array; PostgREST converts it to pgvector’s internal format on insert.
Searching
Vector search uses the distance operators (<=> for cosine, <-> for L2, <#> for negative inner product):
1 - (embedding <=> $1) converts cosine distance (lower = more similar) to similarity (higher = more similar) for client-friendly results.
Via PostgREST RPC:
Hybrid search (vector + BM25)
For RAG-quality retrieval, combine vector similarity with BM25 keyword scoring. You’ll need atsvector column and matching GIN index:
When pgvector isn’t enough
For very large corpora (10M+ embeddings), even HNSW gets slow. Three options:- Use the typed KB surface — Powabase’s KB indexing strategies handle large corpora with techniques like PageIndex and GraphIndex that go beyond flat vector search.
- Specialized vector DB — Pinecone, Weaviate, Qdrant. Add cost; sometimes the right shape for billion-scale workloads.
- Quantization / dimensionality reduction — reduce the embedding size to 256 or 512 dimensions; faster but lower recall.
Next steps
Sources reference
The typed surface for document ingestion if you decide pgvector-direct is too much work.
Knowledge Bases reference
The typed search surface with hybrid retrieval and reranking.
Extensions
What else is preloaded alongside pgvector.
Direct Postgres
For the SQL patterns this guide builds on.