This episode covers ChromaDB's client-server mode: running the server with chroma run, connecting via HttpClient, setting host and port, understanding the tenant and database model, and server configuration for local versus production deployment.

Since episode 2 we have called client-server mode the production recommendation. Episode 12 is where it becomes real: you will run the server, connect clients, set host and port, understand the tenant and database model, and put together the right server configuration for both local and production deployment.
This is a transition episode: from ChromaDB as a library to ChromaDB as a service. All the following episodes — security, deployment, and scaling — assume you are comfortable with this mode.
The ChromaDB server is started with the chroma run command. This runs the modern Rust server recommended for production:
chroma run --path ./data-server --port 8000chroma run --path ./data-server --port 8000 starts the server with persistent data in ./data-server. By default the server listens on localhost:8000.
To make sure the server is alive, check the health endpoint:
curl http://localhost:8000/api/v2/heartbeatThe response from curl http://localhost:8000/api/v2/heartbeat is JSON with a nanosecond timestamp. If it appears, the server is ready to accept requests.
Python clients connect via HttpClient:
import chromadb
client = chromadb.HttpClient(
host="localhost",
port=8000,
)chromadb.HttpClient(host="localhost", port=8000) creates a client that sends all operations to the server. From here, every API you learned in episodes 3-10 works exactly the same — create_collection, add, query, all of them.
Another way to configure the client: through environment variables. chromadb.HttpClient() with no arguments reads settings from the environment:
export CHROMA_SERVER_HOST="localhost"
export CHROMA_SERVER_HTTP_PORT="8000"client = chromadb.HttpClient()chromadb.HttpClient() with no arguments uses CHROMA_SERVER_HOST and CHROMA_SERVER_HTTP_PORT. This approach makes it easy to configure across environments without changing code.
Info
In version 1.x, the Python client uses the REST API (/api/v1 and /api/v2) to reach the server. Make sure the client and server versions are aligned — a major version difference can produce incompatible protocols.
ChromaDB uses a two-level model: tenant and database. Tenants separate logical ownership (for example, per team or per product); databases separate collections within a tenant. By default everything lives in the default_database tenant.
client.create_tenant("tim-data")
client.set_tenant("tim-data")
collection = client.create_collection("analytics")client.create_tenant("tim-data") followed by client.set_tenant("tim-data") directs subsequent operations to that tenant. This model is very useful for shared deployments — we will cover its access control in episode 13.
Inside a tenant, you can separate further with databases:
client.create_database("analytics-db")
client.set_database("analytics-db")client.create_database("analytics-db") creates additional collection space. The tenant and database combination gives you a flexible data separation hierarchy without needing a separate server.
The server reads configuration via environment variables. The most commonly set ones:
export CHROMA_SERVER_HOST="0.0.0.0"
export CHROMA_SERVER_HTTP_PORT="8000"
export CHROMA_SERVER_AUTHN_CREDENTIALS_FILE="/etc/chroma/creds.txt"
chroma runWith CHROMA_SERVER_HOST="0.0.0.0", the server accepts connections from outside localhost — required for deployment. The CHROMA_SERVER_AUTHN_CREDENTIALS_FILE line sets up the authentication that will be covered fully in episode 13.
| Aspect | Local | Production |
|---|---|---|
| Host | localhost | 0.0.0.0 behind a reverse proxy |
| Authentication | Optional | Required |
| Storage | Local path | Persistent volume / object storage |
| Backup | Manual | Scheduled |
| Monitoring | None | Health checks + metrics |
For production, do not expose the server directly to the internet. Put it behind a reverse proxy with TLS, enable authentication, and connect it to persistent storage. Deployment details will be covered in episode 15.
Episode 12 brought ChromaDB from a library to a service: running the server with chroma run, connecting clients via HttpClient with host and port, configuring via environment, understanding the tenant and database model for data separation, and putting together the settings that distinguish local from production deployment.
Key takeaways:
chroma run runs the Rust server; curl /api/v2/heartbeat verifies it.HttpClient makes the entire ChromaDB API work over HTTP.localhost host for local; 0.0.0.0 behind a proxy for production.In the next episode, episode 13, we will discuss authentication and authorization — the default no-auth condition, token-based auth, BasicAuth, server auth configuration, and per-collection and per-tenant access control in shared deployments. Your server is opening up; time to lock it down.