title: ChromaDB description: Developer-friendly vector database — ChromaDB for RAG: embeddings, metadata filtering, persistence, and integration with LangChain and LlamaIndex. category: 09-RAG tags: [chroma, chromadb, vector-store, rag, developer] status: ready last_updated: 2026-09-06
ChromaDB¶
Chroma is the developer-friendly vector database. It runs in-process (no server needed), persists to disk, and integrates seamlessly with LangChain and LlamaIndex. Use Chroma when you want a simple, local vector DB without the overhead of FAISS setup or a managed service.
Table of Contents¶
- Installation / Setup
- Core Syntax
- Common Operations
- Practical Examples
- Common Patterns
- Best Practices
- Common Mistakes
- Troubleshooting
- Related Cheat Sheets
- Official Documentation
Installation / Setup¶
Core Syntax¶
Basic usage¶
import chromadb
# create a client (in-memory by default)
client = chromadb.Client()
# or persistent client (saves to disk)
client = chromadb.PersistentClient(path="./chroma_db")
# create a collection
collection = client.get_or_create_collection(
name="documents",
metadata={"hnsw:space": "cosine"}, # or "l2", "ip"
)
# add documents
collection.add(
documents=["Python is great for ML", "JavaScript runs in browsers"],
ids=["doc1", "doc2"],
metadatas=[{"source": "tutorial"}, {"source": "web"}],
)
# query
results = collection.query(query_texts=["data analysis"], n_results=3)
print(results["documents"]) # [['Python is great for ML']]
print(results["distances"]) # [[0.35]] (lower = more similar for cosine)
Collection settings¶
collection = client.get_or_create_collection(
name="my_docs",
metadata={
"hnsw:space": "cosine", # "cosine", "l2", or "ip"
"hnsw:M": 16, # connections per node (default 16)
"hnsw:ef_construction": 200, # build quality (default 200)
},
)
LangChain + Chroma¶
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
# create from documents
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=OpenAIEmbeddings(),
collection_name="my_docs",
persist_directory="./chroma_db", # optional: persist to disk
)
# search
docs = vectorstore.similarity_search("query", k=5)
# with metadata filter
docs = vectorstore.similarity_search(
"query", k=5, filter={"source": "report.pdf"}
)
LlamaIndex + Chroma¶
import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import VectorStoreIndex, StorageContext
chroma_client = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = chroma_client.get_or_create_collection("my_docs")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
Common Operations¶
Metadata filtering¶
# exact match
results = collection.query(
query_texts=["query"],
where={"source": "report.pdf"},
)
# comparison operators
results = collection.query(
query_texts=["query"],
where={"year": {"$gte": 2024}},
)
# logical operators
results = collection.query(
query_texts=["query"],
where={"$and": [{"source": "report"}, {"year": {"$gte": 2024}}]},
)
Update and delete¶
# update
collection.update(
ids=["doc1"],
metadatas=[{"source": "updated_source"}],
)
# delete
collection.delete(ids=["doc1"])
collection.delete(where={"source": "old_source"})
Collection management¶
# list collections
collections = client.list_collections()
# get collection
collection = client.get_collection("my_docs")
# count documents
print(collection.count())
# delete collection
client.delete_collection("my_docs")
Practical Examples¶
Example 1 — Full RAG with Chroma¶
import chromadb
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# build Chroma store
vectorstore = Chroma.from_documents(
chunks, OpenAIEmbeddings(), persist_directory="./chroma_db")
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# RAG chain
rag = (
{"context": retriever | (lambda d: "\n\n".join(x.page_content for x in d)),
"question": RunnablePassthrough()}
| ChatPromptTemplate.from_template("Answer:\n{context}\n\nQ: {question}")
| ChatOpenAI(model="gpt-4o")
| StrOutputParser()
)
Example 2 — ChromaDB standalone (no LangChain)¶
import chromadb
from openai import OpenAI
client_oa = OpenAI(api_key="YOUR_API_KEY")
client = chromadb.PersistentClient(path="./my_db")
collection = client.get_or_create_collection("docs")
def embed(texts):
return client_oa.embeddings.create(model="text-embedding-3-small", input=texts)
# add with embeddings
response = embed(["doc1 text", "doc2 text"])
collection.add(
documents=["doc1 text", "doc2 text"],
embeddings=[e.embedding for e in response.data],
ids=["1", "2"],
)
# query with embedding
query_emb = embed(["search query"])
results = collection.query(query_embeddings=query_emb.data[0].embedding, n_results=3)
Common Patterns¶
Pattern: persistent Chroma for RAG app¶
from langchain_community.vectorstores import Chroma
# first run: create and persist
vectorstore = Chroma.from_documents(chunks, embeddings, persist_directory="./db")
# subsequent runs: load from disk
vectorstore = Chroma(persist_directory="./db", embedding_function=embeddings)
Pattern: multi-tenant Chroma¶
# separate collections per tenant
for tenant_id in tenant_ids:
collection = client.get_or_create_collection(
name=f"docs_{tenant_id}",
metadata={"hnsw:space": "cosine"},
)
Best Practices¶
- Use Chroma for local development and small-to-medium datasets.
- Use PersistentClient for persistence —
Client()is in-memory only. - Chroma uses its own embedding function by default — pass your own for custom models.
- Metadata filtering is a key advantage over FAISS.
- Chroma is not for production scale (>1M vectors) — use Qdrant, Pinecone, or Weaviate.
Common Mistakes¶
| Mistake | Fix |
|---|---|
Using Client() in production |
Use PersistentClient(path="./db") |
| Not persisting | Chroma in-memory loses data on restart |
| Expecting production scale | Chroma is for dev/small; use managed DB for production |
| Wrong distance metric | Check hnsw:space: cosine for normalized, l2 for raw |
Troubleshooting¶
| Symptom | Cause / Fix |
|---|---|
| Data lost after restart | Not using PersistentClient |
Dimension mismatch |
Embedding model changed — re-embed |
| Slow queries on large data | Chroma is not optimized for >1M vectors |
Collection not found |
Check collection name; use get_or_create_collection |
Related Cheat Sheets¶
- faiss.md — faster local alternative
- qdrant.md — production alternative
- rag.md — the complete pipeline
- langchain — LangChain integration
- llamaindex — LlamaIndex integration
Official Documentation¶
- ChromaDB docs — https://docs.trychroma.com/
- ChromaDB GitHub — https://github.com/chroma-core/chroma
Last Updated¶
2026-09-06 — Initial version.