Vector Databases Explained: Pinecone, Chroma & pgvector
📖 11 min read · AI & Machine Learning · AI Prompt Builder →
Why Regular Databases Can't Do This
Traditional databases are great at exact matches: find all users where age = 30, or full-text search for documents containing "machine learning". But they can't answer questions like "find me documents that are semantically similar to this query" — because they don't understand meaning.
Vector databases solve this by storing data as high-dimensional vectors (embeddings) and enabling fast approximate nearest neighbor (ANN) search — finding the most similar vectors to a query vector in milliseconds, even across millions of records.
How Embeddings Capture Meaning
An embedding model converts text (or images, audio, etc.) into a fixed-size vector of numbers. Similar content produces similar vectors — measured by cosine similarity or dot product.
ANN Algorithms: How Fast Search Works
Brute-force search (compare query to every vector) is too slow at scale. Vector databases use ANN algorithms:
Graph-based algorithm. Builds a multi-layer graph where each node connects to its nearest neighbors. Very fast queries, high recall. Used by Chroma, Weaviate, Qdrant.
Clusters vectors into groups, searches only the most relevant clusters. Good for very large datasets. Used by Faiss, Pinecone.
Compresses vectors to reduce memory usage. Trades some accuracy for much lower RAM requirements. Often combined with IVF.
Exact search — compares query to every vector. 100% recall but O(n) time. Only practical for small datasets (<100K vectors).
Pinecone: Managed Vector Database
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: process.env.PINECONE_API_KEY });
const index = pc.index('my-index');
// Upsert vectors
await index.upsert([
{ id: 'doc1', values: [0.1, 0.2, ...], metadata: { text: 'Hello world', source: 'docs' } },
{ id: 'doc2', values: [0.3, 0.4, ...], metadata: { text: 'AI is amazing', source: 'blog' } },
]);
// Query for similar vectors
const results = await index.query({
vector: queryEmbedding, // Your query converted to embedding
topK: 5,
includeMetadata: true,
filter: { source: { $eq: 'docs' } }, // Optional metadata filter
});
results.matches.forEach(match => {
console.log(match.score, match.metadata.text);
});Chroma: Local Development
import { ChromaClient, OpenAIEmbeddingFunction } from 'chromadb';
const client = new ChromaClient(); // Runs locally by default
const embedder = new OpenAIEmbeddingFunction({
openai_api_key: process.env.OPENAI_API_KEY,
openai_model: 'text-embedding-3-small',
});
const collection = await client.getOrCreateCollection({
name: 'my-docs',
embeddingFunction: embedder,
});
// Add documents (Chroma handles embedding automatically)
await collection.add({
ids: ['doc1', 'doc2'],
documents: ['Hello world', 'AI is amazing'],
metadatas: [{ source: 'docs' }, { source: 'blog' }],
});
// Query by text (Chroma embeds the query automatically)
const results = await collection.query({
queryTexts: ['What is artificial intelligence?'],
nResults: 3,
});pgvector: If You Already Use PostgreSQL
-- Enable the extension
CREATE EXTENSION IF NOT EXISTS vector;
-- Create table with vector column
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536) -- OpenAI text-embedding-3-small dimension
);
-- Insert with embedding
INSERT INTO documents (content, embedding)
VALUES ('Hello world', '[0.1, 0.2, ...]'::vector);
-- Find 5 most similar documents (cosine similarity)
SELECT content, 1 - (embedding <=> '[0.15, 0.25, ...]'::vector) AS similarity
FROM documents
ORDER BY embedding <=> '[0.15, 0.25, ...]'::vector
LIMIT 5;
-- Create HNSW index for fast search
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);Choosing the Right Vector Database
Build RAG Pipelines with DevBench
Use our AI tools to prototype prompts and count tokens for your vector search applications.