Runs Chroma (chromadb) locally or as a server: PersistentClient, create_collection/add/query/get, metadata where filters, and LangChain or LlamaIndex vector stores. Use when building self-hosted RAG, notebook semantic search, or embedding documents with metadata. Not for managed Pinecone indexes, FAISS-only kNN without metadata, or Weaviate GraphQL clusters.
Runs Chroma (chromadb) locally or as a server: PersistentClient, create_collection/add/query/get, metadata where filters, and LangChain or LlamaIndex vector stores. Use when building self-hosted RAG, notebook semantic search, or embedding documents with metadata. Not for managed Pinecone indexes, FAISS-only kNN without metadata, or Weaviate GraphQL clusters.
The AI-native database for building LLM applications with memory. Simple 4-function API: create_collection, add, query, get. Scales from notebooks to production clusters.
When to Use
Use Chroma when:
Building RAG (retrieval-augmented generation) applications
Need local or self-hosted vector database
Want open-source solution (Apache 2.0)
Prototyping in notebooks with semantic search
Storing embeddings with metadata and filtering by that metadata
Need document retrieval with vector + full-text search
Use alternatives instead:
Pinecone: Managed cloud, auto-scaling, no infrastructure management
FAISS: Pure similarity search, no metadata support
Weaviate: Production ML-native database with GraphQL API
Qdrant: High performance, Rust-based, production filtering
Metrics:
24,300+ GitHub stars, 1,900+ forks
v1.3.3+ (stable, weekly releases)
Apache 2.0 license
Prerequisites
Python 3.8+ (or Node.js 18+ for JS/TS client)
Install Chroma and default embedding dependencies:
# Get by IDs
docs = collection.get(ids=["id1", "id2"])
# Get with filters
docs = collection.get(
where={"category": "tutorial"},
limit=10
)
# Get all documents
docs = collection.get()
# Delete by IDs
collection.delete(ids=["id1", "id2"])
# Delete with filter
collection.delete(where={"source": "outdated"})
7. Persistent Storage
# Persist to disk — data saved automatically
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.create_collection("my_docs")
collection.add(documents=["Doc 1"], ids=["id1"])
# Reload later with same path
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_collection("my_docs")
8. Custom Embedding Functions
Default (Sentence Transformers — no API key needed):
# Uses sentence-transformers all-MiniLM-L6-v2 by default
collection = client.create_collection("my_docs")
# Start Chroma server (terminal)
chroma run --path ./chroma_db --port 8000
# Connect to running serverimport chromadb
from chromadb.config import Settings
client = chromadb.HttpClient(
host="localhost",
port=8000,
settings=Settings(anonymized_telemetry=False)
)
# Use as normal
collection = client.get_or_create_collection("my_docs")
10. LangChain Integration
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
# Split documents
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000)
docs = text_splitter.split_documents(documents)
# Create Chroma vector store
vectorstore = Chroma.from_documents(
documents=docs,
embedding=OpenAIEmbeddings(),
persist_directory="./chroma_db"
)
# Query
results = vectorstore.similarity_search("machine learning", k=3)
# As retriever
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
11. LlamaIndex Integration
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import VectorStoreIndex, StorageContext
import chromadb
# Initialize Chroma
db = chromadb.PersistentClient(path="./chroma_db")
collection = db.get_or_create_collection("my_collection")
# Create vector store
vector_store = ChromaVectorStore(chroma_collection=collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# Create index
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context
)
# Query
query_engine = index.as_query_engine()
response = query_engine.query("What is machine learning?")
Pitfalls
In-memory client loses data on restart — Always use PersistentClient(path=...) for any data you need to keep. The default chromadb.Client() is in-memory only.
Embedding function mismatch — You cannot query a collection with a different embedding function than the one used to create it. Embeddings from different models are not comparable.
Duplicate IDs silently overwrite — Adding documents with existing IDs will overwrite the previous content without warning. Use unique IDs to avoid data loss.
Metadata values must be primitives — Chroma metadata supports str, int, float, and bool values only. Lists, dicts, or nested objects are not supported as metadata values.
$in operator requires list values — The where_document filter does not support $in; only where metadata filters support $in with a list of values.
Server mode port conflicts — Ensure port 8000 (or your chosen port) is free before starting chroma run. Check with netstat -ano | findstr :8000 on Windows or lsof -i :8000 on Linux/macOS.
Telemetry enabled by default — Set anonymized_telemetry=False in Settings to disable telemetry if required.
Large batch adds can timeout — For collections with 10,000+ documents, add in batches of 1,000-5,000 to avoid memory issues.
No built-in authentication in server mode — Chroma server does not include authentication. Do not expose it to the public internet without a reverse proxy with auth.
Collection name restrictions — Collection names must be 3-63 characters, start/end with alphanumeric, and contain only alphanumeric, underscores, or hyphens.
Verification
Verify installation:
python -c "import chromadb; print(chromadb.__version__)"# Expected output: 1.3.3 or higher