> **TL;DR.** Vector databases store high-dimensional embeddings and retrieve them by similarity—the core primitive behind semantic search, RAG, and agent memory. The right choice depends on whether you need a managed service that ships fast, a self-hosted option you control completely, or an extension bolted onto Postgres you already operate. This guide cuts through the noise and gives you enough to pick, configure, and use one in production.
What a Vector Database Actually Does
A relational database finds rows where `user_id = 42`. A vector database finds rows whose *meaning* is closest to a query. You convert text, images, or structured data into a dense numerical vector (an embedding) using a model like `text-embedding-3-small` or `nomic-embed-text`, then store that vector alongside a payload. At query time, you embed the query the same way and retrieve the *k* nearest vectors by cosine similarity, dot product, or Euclidean distance.
The critical insight: the quality of retrieval depends more on embedding consistency—using the same model for indexing and querying—than on which vector database you pick. Switching from Chroma to Pinecone won't fix a retrieval problem caused by mismatched embedding models.
The Main Contenders
Managed, serverless
- **Pinecone** — the incumbent. Serverless tier is free up to a stored-vector threshold; paid tiers price by pod or serverless usage. Excellent client libraries, no ops work, regional data control. Lock-in risk is real.
- **Weaviate Cloud** — managed Weaviate with a generous free sandbox. Strong GraphQL API, built-in module system for embedding at insert time.
Self-hosted / open-source
- **Qdrant** — written in Rust, fast, low memory footprint. Best-in-class filtering: payload conditions are first-class, not post-retrieval. Docker image is under 100 MB. Binary quantization support reduces memory by 40× with minimal recall loss.
- **Weaviate (self-hosted)** — Helm chart for Kubernetes, strong multi-tenancy story for SaaS products. More configuration surface than Qdrant.
- **Chroma** — designed for fast local prototyping. In-memory or persistent SQLite backend. Not production-hardened at scale, but the fastest path from idea to running similarity search.
- **Milvus** — enterprise-scale, supports billions of vectors, etcd + MinIO dependency stack is heavy. Relevant if you're operating at data-warehouse scale.
Postgres extensions
- **pgvector** — adds a `vector` column type and `<->` / `<#>` / `<=>` operators for L2, inner product, and cosine. Works with any hosted Postgres. IVFFlat and HNSW index types available since pgvector 0.5.
- **Supabase Vector** — Supabase ships pgvector out of the box with storage, auth, and edge functions in the same project. If you're already on Supabase, this is the zero-friction path.
How to Choose
Work through these in order:
1. **Already on Postgres?** Start with pgvector or Supabase Vector. You eliminate a network hop, stay in SQL, and keep one infrastructure dependency.
2. **Need sub-100ms p99 at production scale?** pgvector's HNSW is competitive up to a few million vectors. Beyond that, dedicated systems win.
3. **Need complex metadata filtering?** Qdrant's payload filtering evaluates conditions before the ANN search, not after. This matters when your filter is selective (e.g., `tenant_id = X AND category IN [...]`).
4. **Building a multi-tenant SaaS?** Qdrant collections-per-tenant or Weaviate's multi-tenancy API both work. Namespaces in Pinecone serverless are the managed equivalent.
5. **Prototyping and just need something to run?** Chroma locally, Supabase Vector in the cloud.
Setting Up in Practice
pgvector in Supabase (SQL)
```sql
-- Enable extension
create extension if not exists vector;
-- Table
create table documents (
id bigint primary key generated always as identity,
content text,
embedding vector(1536)
);
-- HNSW index
create index on documents
using hnsw (embedding vector_cosine_ops)
with (m = 16, ef_construction = 64);
-- Query
select id, content
from documents
order by embedding <=> '[...]'::vector
limit 5;
```
Qdrant (Docker + Python)
```bash
docker run -p 6333:6333 qdrant/qdrant
```
```python
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
client = QdrantClient("localhost", port=6333)
client.create_collection(
collection_name="docs",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)
client.upsert(
collection_name="docs",
points=[PointStruct(id=1, vector=[...], payload={"text": "...", "tenant": "acme"})],
)
results = client.search(
collection_name="docs",
query_vector=[...],
query_filter={"must": [{"key": "tenant", "match": {"value": "acme"}}]},
limit=5,
)
```
This is the full cycle: create collection, upsert with payload, filtered search. Works the same pattern in production.
Indexing Strategy and Performance
Two index types dominate:
- **IVFFlat** — divides the vector space into *n* clusters, probes the nearest clusters at query time. Fast to build, lower memory, but recall drops when `nprobe` is set too low. Good for cold-start indexing on large datasets.
- **HNSW (Hierarchical Navigable Small World)** — graph-based, higher memory, but better recall at equivalent query latency. Now the default recommendation for most production workloads.
Critical tuning knobs:
- `m` (HNSW): edges per node. 16 is a safe default; 32 improves recall at higher memory cost.
- `ef_construction`: build-time search width. Higher = better graph quality, slower indexing.
- `ef_search` / `ef` at query time: controls recall vs latency tradeoff at runtime.
Binary quantization in Qdrant can drop memory from gigabytes to hundreds of megabytes for large collections, with rescoring from original vectors recovering most of the recall loss.
Use Cases That Actually Ship
**RAG (retrieval-augmented generation)** — the most common production pattern. Chunk documents, embed with a consistent model, store. At query time, retrieve top-k chunks, inject into the context window, generate. The quality ceiling is document chunking strategy more than vector db choice. See [AI for Backend Developers 2026](/en/rehberler/ai-backend-developers-2026) for integration patterns with LLM APIs.
**Agent memory** — store conversation turns or tool outputs as vectors, retrieve contextually relevant past interactions. Stateless agents become stateful without ballooning the context window. Pairs naturally with [AI Model Context Protocol (MCP) 2026](/en/rehberler/ai-mcp-2026) when building multi-agent systems.
**Semantic search over structured data** — embed product descriptions, job listings, or support tickets. Users search in natural language; results are relevance-ranked, not keyword-matched. Dramatically reduces zero-result searches compared to full-text search.
**Recommendation** — embed user action sequences or item metadata into the same space, retrieve nearest neighbors. Item-to-item and user-to-item recommendations from a single index.
**Image/multi-modal similarity** — embed images with a vision encoder (CLIP variants), store alongside text embeddings in separate namespaces, or use a model that produces joint embeddings. Reverse image search and visual duplicate detection follow the same pattern as text RAG.
Pricing Reality
If you're a solo developer or small team, start on the free tier of whatever matches your existing stack. Migrate to dedicated infrastructure when query latency or stored-vector limits become real constraints—not theoretical ones.
For database admins evaluating vector workloads alongside existing Postgres operations, [AI for Database Admins 2026](/en/rehberler/ai-database-admins-2026) covers the operational side. For the full-stack view of embedding AI vector databases into a production app, [AI for Full-Stack Developers 2026](/en/rehberler/ai-fullstack-developers-2026) walks through the end-to-end integration.
Common Failure Modes
- **Embedding model drift** — updating the embedding model without re-indexing existing vectors corrupts retrieval. Version your embeddings. Treat a model swap as a migration, not a config change.
- **Chunking too coarse** — retrieving 10,000-token chunks burns context window and dilutes relevance. Target 256–512 tokens per chunk with overlap, tested against your actual query distribution.
- **Ignoring payload filters** — running ANN search and then filtering results in application code wastes compute and returns fewer results than requested. Use native payload filtering.
- **No recall evaluation** — shipping RAG without measuring retrieval recall is flying blind. A simple evaluation: sample 50 queries with known good documents, measure what fraction appear in top-5 results.
Next Steps
- If you're on Supabase already, enable pgvector and test RAG on your existing dataset before evaluating alternatives.
- For filtering-heavy production workloads, run Qdrant locally with Docker and benchmark your actual query patterns before committing to a managed service.
- Evaluate embedding models independently of the vector db—`nomic-embed-text` (open-weight, runs locally) vs `text-embedding-3-small` (OpenAI, cheap, high quality) will have more impact on retrieval quality than db choice.
- Add a retrieval recall metric to your CI pipeline before the system grows.