pgvector Chroma Qdrant and Pinecone

Comparison

pgvectorChromaQdrantPinecone
WhatPostgreSQL extensionOpen-source embedded DBOpen-source vector DB (Rust)Managed cloud service
Run itYour Postgres (also Supabase, Neon, AWS RDS)Inside your Python process or as a serverDocker / Qdrant CloudServerless, nothing to run
Best forApps already on Postgres; SQL joins with business dataPrototypes, notebooks, small appsProduction with rich filters, self-hostedTeams that want zero ops at scale
FiltersFull SQL WHERESimple where dictsRich payload filtersMetadata filters

Also common: FAISS (a library, not a database, from Meta; very fast in-memory search), Weaviate, Milvus, Elasticsearch/OpenSearch and MongoDB Atlas vector search.

pgvector

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE faq_chunks (
  id        bigserial PRIMARY KEY,
  content   text NOT NULL,
  category  text,
  embedding vector(1024)
);
CREATE INDEX ON faq_chunks USING hnsw (embedding vector_cosine_ops);

-- <=> is cosine distance (smaller = closer); $1 is the query vector from your code
SELECT id, content, 1 - (embedding <=> $1) AS similarity
FROM faq_chunks
WHERE category = 'returns'
ORDER BY embedding <=> $1
LIMIT 5;

Chroma

import chromadb

client = chromadb.PersistentClient(path="./chroma_db")
faqs = client.get_or_create_collection("shopease_faqs", metadata={"hnsw:space": "cosine"})

texts = ["Refunds take 5-7 working days.", "Orders above Rs 499 ship free."]
faqs.add(
    ids=["faq-1", "faq-2"],
    documents=texts,
    metadatas=[{"category": "returns"}, {"category": "delivery"}],
    embeddings=embed_documents(texts),          # e.g. Voyage AI vectors
)
result = faqs.query(query_embeddings=[embed_query("money back kab milega")], n_results=1,
                    where={"category": "returns"})
print(result["documents"][0], result["distances"][0])

Run it

python chroma_demo.py

Example output

['Refunds take 5-7 working days.'] [0.31]

Pinecone

from pinecone import Pinecone

pc = Pinecone()                       # reads PINECONE_API_KEY
index = pc.Index("shopease-products")
index.upsert(vectors=[{"id": "P1", "values": vec_p1, "metadata": {"price": 2499, "category": "footwear"}}])
res = index.query(vector=query_vec, top_k=5, include_metadata=True,
                  filter={"price": {"$lte": 3000}, "category": {"$eq": "footwear"}})
for m in res.matches:
    print(m.id, round(m.score, 3), m.metadata)