Skip to content

Install Chroma 1.5.9 Embedded Vector Database

Deploy Chroma 1.5.9 as an embedded vector database with pip or Docker. Specs, PersistentClient setup, verify steps, and real install fixes.

7 min readIntermediate

Here’s the bit almost nobody puts on the install page: Chroma’s HNSW index has to live entirely in RAM. For typical 1024-dimensional embeddings, the single-node performance guide puts max collection size at roughly N ≈ R × 0.245 million vectors (N in millions, R = RAM in GB). Under 2GB system RAM is not recommended. That math matters more than the pip one-liner when you treat Chroma as an embedded vector database.

This guide deploys Chroma 1.5.9 (current stable chromadb on PyPI as of May 2026) for local embedded use – PersistentClient on disk, optional client-server, Docker if you want a process boundary. Commands first. Theory later, if at all.

System requirements before you install

Python ≥ 3.9. That’s the floor on the PyPI classifiers for 1.5.9. OS-independent package, with native wheels for manylinux x86_64/aarch64, macOS x86_64/arm64, and Windows amd64.

Resource Minimum Comfortable for real work
RAM 2 GB (official floor) 8-16 GB+ → ~1.7M-3.6M of 1024-d vectors via the formula
CPU 1 core 2+ vCPUs if you embed and query at once
Disk a few GB free at least RAM size + headroom; SSD preferred
Python 3.9+ 3.10+ (often newer SQLite)
Docker (optional) working Engine + pull access volume mount you actually control

Latency does not ease off when the index spills. Swap starts and the box feels dead. Size RAM from the formula, then leave about 1GB for everything else on the machine.

Official download sources for Chroma 1.5.9

Skip random mirrors. Use these only:

Pin :1.5.9. :latest is fine until it isn’t – main drifts; install day wants the tagged stable.

Install Chroma 1.5.9 step by step

Embedded path that works: virtualenv + pip. Library, default embedding stack, and the chroma CLI land together.

# 1. Fresh venv (Linux/macOS)
python3 -m venv .venv
source .venv/bin/activate

# Windows PowerShell
# python -m venv .venv
# ..venvScriptsActivate.ps1

# 2. Upgrade installer tooling
python -m pip install --upgrade pip

# 3. Install exact stable release
pip install "chromadb==1.5.9"

# 4. Confirm package version
python -c "import chromadb; print(chromadb.__version__)"

Expect 1.5.9. No chroma on PATH inside the venv? Call the script from the venv’s bin, or pipx install chromadb for a global CLI without touching system Python (CLI install docs).

Brief alternatives: JS/TS → npm install chromadb then npx chroma run --path ./data. Process isolation → Docker below. HTTP-only Python client → chromadb-client when the server already runs elsewhere.

First-time configuration (minimum viable embedded setup)

chromadb.Client() is a 30-second smoke test. Process exits, data is gone. For a real on-disk store, use PersistentClient and a path you own:

import chromadb
from pathlib import Path

data_dir = Path("./chroma-data").resolve()
data_dir.mkdir(parents=True, exist_ok=True)

client = chromadb.PersistentClient(path=str(data_dir))

collection = client.get_or_create_collection(name="local_embed_store")
collection.upsert(
 ids=["cfg-1"],
 documents=["Embedded Chroma 1.5.9 configuration check"],
 metadatas=[{"env": "local"}],
)
print(client.heartbeat())
print(collection.count())

Omit path and you get .chroma in the working directory – easy to lose across projects. Set it on purpose.

Same machine, separate process:

chroma run --path ./chroma-data --host localhost --port 8000

Connect with chromadb.HttpClient(host="localhost", port=8000). Docker form from the Docker deploy guide:

docker run --rm -v "$(pwd)/chroma-data:/data" -p 8000:8000 chromadb/chroma:1.5.9

Optional /config.yaml mount exists in that guide if you need server-side knobs. Keep reset disabled on any volume you care about so one sloppy client call cannot wipe it.

Think of PersistentClient like SQLite for vectors: same process, files on disk, zero network until you outgrow the laptop. That model keeps config boring – in a good way – and stops the “three servers, three folders, where did my collection go?” loop.

Verify the install actually works

Three checks, in order: import/version, heartbeat, round-trip write.

python - <<'PY'
import chromadb
print("version", chromadb.__version__)
c = chromadb.PersistentClient(path="./chroma-data")
print("heartbeat_ns", c.heartbeat())
col = c.get_or_create_collection("verify")
col.upsert(ids=["v1"], documents=["ping"])
assert col.count() >= 1
print("ok", col.get(ids=["v1"]))
PY

Server or Docker: hit the heartbeat endpoint the running process exposes (docs show the HTTP client path). Connection refused means nothing is listening. Heartbeat OK but the app still fails? Wrong host/port, or the client’s data path is not the server’s --path//data.

Common install errors and fixes

Match the message. Smallest fix wins. These are the ones that show up in issues and deploy logs (troubleshooting docs):

  • “Your system has an unsupported version of sqlite3” / Chroma requires SQLite > 3.35 – Newer Python (3.10+ often helps). Linux: pip install pysqlite3-binary, then override sqlite3 before importing chromadb. Windows: replace the SQLite DLL next to that Python. Debian images: bookworm or newer.
  • Failed to build wheels for hnswlibexport HNSWLIB_NO_NATIVE=1, reinstall. Mac: xcode-select --install. Windows: follow the build toolchain notes linked from troubleshooting.
  • Illegal instruction (core dumped) in Docker – image/CPU arch mismatch. Pull or build the tag that matches the machine that runs it.

Pip stuck on download? Pin 1.5.9 and retry on a cleaner network path. Binary wheels exist for the common platforms; you should not be compiling the world unless the wheel miss-matches your arch.

Upgrade, vacuum, and uninstall

pip install -U "chromadb==1.5.9"
python -c "import chromadb; print(chromadb.__version__)"

The catch: data directories that lived on Chroma before v0.5.6 can keep an unpruned write-ahead log. After you upgrade, run vacuum once so the dir shrinks and continuous pruning turns on (migration notes):

chroma utils vacuum --path ./chroma-data

Brand-new 1.5.x dirs already prune. Don’t cron vacuum “just in case.”

Uninstall / cleanup:

# Package
pip uninstall chromadb -y

# Optional thin client
pip uninstall chromadb-client -y

# Data (destructive)
rm -rf ./chroma-data ./.chroma

# Docker
docker rm -f $(docker ps -aq --filter ancestor=chromadb/chroma:1.5.9) 2>/dev/null
docker volume prune -f # only if you used named volumes you no longer need

pipx CLI: pipx uninstall chromadb. Curl-installed binaries: remove whatever path the standalone installer used.

Honest question worth sitting with: how many “local RAG stacks” are three containers and a reverse proxy when a venv and PersistentClient would have held the whole prototype? Complexity is optional until a second language or a second user shows up.

FAQ

Is Chroma 1.5.9 free for embedded local use?

Yes. Apache 2.0 on the open-source server and Python package. Chroma Cloud is separate billing – you do not need it for PersistentClient or self-hosted Docker.

Should I use PersistentClient or Docker for a laptop RAG prototype?

Python, single user, one project folder? PersistentClient. Fewer moving parts. Move to chroma run or chromadb/chroma:1.5.9 when another language needs HTTP, you want process isolation, or you are staging a small VPS. Point both at the same host path//data volume if you switch – never two writers on one directory.

Why does heartbeat succeed but my old collection “disappear”?

Path mismatch, almost every time. Ephemeral Client() never touches disk. PersistentClient(path="./chroma-data") from project A is not Docker’s /data unless that exact host path is mounted. Print Path(path).resolve() in the app and compare it to the server’s --path. Second gotcha: a startup reset() empties the store while heartbeat still looks healthy on the empty DB. Confirm you are not wiping on boot before you chase networking ghosts.

Next: create the venv, pin chromadb==1.5.9, run the verify snippet on ./chroma-data, point the embed pipeline at that same path. Heartbeat prints and count() survives a process restart? Install is done.