skip to content

Persistence and Deployment

Chroma runs in-memory, on local disk, or as a client-server process, and teams get burned by assuming the default persists. This covers the client modes and what running it as a real service involves.

on this pageshow

questions

6

In Chroma, what is the difference between EphemeralClient and PersistentClient?

level: juniorimportance: must knowfreq 80%

answer

  1. three constructors, three storage owners
  2. the default is not durable
  3. a path argument, not a method call
  4. EphemeralClient vs PersistentClient(path) vs HttpClient

basics

~20 s

EphemeralClient keeps collections in memory only and loses everything when the process exits. PersistentClient(path="./chroma") writes to that directory and reloads it on the next run. Plain chromadb.Client() is ephemeral, which is why prototype data disappears.

solid answer

~50 s

Chroma's Python package ships several client constructors and they differ only in where the data lives. `chromadb.EphemeralClient()` — and the bare `chromadb.Client()`, which defaults to the same thing — holds collections in process memory; when the script or notebook kernel ends, the data is gone. `chromadb.PersistentClient(path="./chroma")` points at a directory on local disk and writes there as you go, so a second run of the same script sees the collections it created before. `chromadb.HttpClient(host=..., port=...)` stores nothing locally at all: it talks to a separate Chroma server process that owns the storage. The common trap is that persistence is opt-in through the constructor — there is no `persist()` call to make in modern Chroma, and no flag that turns an ephemeral client into a durable one after the fact. Pick the constructor that matches the lifetime you need.

go deeper

for a junior

Memorise the three constructors and what each one owns: EphemeralClient is memory-only, PersistentClient takes a path on disk, HttpClient talks to a server. Say plainly that the bare Client() is ephemeral.

for a middle

Explain that writes through PersistentClient land on disk as they happen and that the old persist() call no longer exists, so the only decision point is the constructor. Mention that the collection API is identical across all three.

for a senior

Show you have hit the failure in production: a quickstart client deployed as-is, data gone after a restart, no error anywhere. Talk about pinning an absolute path and about when a single-process embedded store stops being appropriate.

for a principal

Frame the choice as a data-ownership decision rather than an API one — who owns the bytes, what the restore path is, and what the migration costs when the prototype's embedded store has to become a service that several processes share.

## The three client constructors Chroma is unusual among vector stores in that the same Python package can be an in-memory library, an embedded on-disk database, or a thin client to a remote server. Which one you get is decided by the constructor you call, and nothing else. - `chromadb.EphemeralClient()` — everything (collection metadata, documents, embeddings, the vector index) lives in the process's memory. When the interpreter exits, it is gone. `chromadb.Client()` with no settings is the same thing: in-memory is the default. - `chromadb.PersistentClient(path="./chroma")` — Chroma manages a directory on the local filesystem. The `path` argument defaults to `./chroma` relative to the working directory. Data written through this client survives process restarts and is reloaded when you construct a client on the same path again. - `chromadb.HttpClient(host="localhost", port=8000)` — no local storage. Every call is an HTTP request to a Chroma server that holds the data. There is also `chromadb.AsyncHttpClient` for asyncio applications. After construction, the collection API is identical across all three. `get_or_create_collection`, `add`, `query`, `get`, `delete` behave the same way; only durability and who owns the bytes change. That uniformity is deliberate — it lets you prototype in memory and move to a server without rewriting query code — but it is also why the mistake is so easy to make: nothing in the collection API tells you whether your data is being kept. ## Persistence is automatic, not a method call Older Chroma tutorials (0.3-era) show a pattern where you construct a client with a `persist_directory` setting and then call `client.persist()` before shutting down, or lose the data. That API is long gone. In current Chroma, a `PersistentClient` writes as part of the operation — once `add` or `upsert` returns, the data is on disk. There is no flush step to forget. The modern failure mode is different and quieter: someone follows a quickstart that uses `chromadb.Client()`, ingests a few thousand documents, sees queries work, deploys it, and discovers after the first restart that the collection is empty. Nothing errored. The fix is a one-word constructor change, but only if you know the default. ## Reconstructing the same client Calling `chromadb.PersistentClient(path="./chroma")` twice in the same process gives you a client over the same underlying storage rather than two independent copies — Chroma keeps a shared instance per path/settings. That is convenient inside one application, but it does not extend across processes: two separate OS processes opening the same directory each get their own file handles and their own in-memory copy of the vector index, which is a real operational hazard for multi-worker web servers. Deleting the directory deletes the database. There is also `client.reset()`, which wipes everything, but it is disabled unless the client was constructed with `allow_reset=True` in its settings — a guard specifically so a stray call cannot nuke a persistent store. ## Choosing between them Use `EphemeralClient` for unit tests and notebooks: it is fast, needs no cleanup, and each test gets a clean slate for free. Use `PersistentClient` for a single-process application, a CLI tool, or a local RAG prototype where one process owns the data and durability across restarts matters. Use `HttpClient` as soon as more than one process needs to read or write the same data, or when the storage should outlive the application container — for example a web app with several workers, or an ingestion job and a serving app that share a corpus. One caveat when moving from persistent to server mode: the persistent path is local to whichever machine ran the client, so "just switch to HttpClient" also means moving the data to wherever the server keeps it. That is a copy of the data directory, not a config toggle. ## What interviewers are checking The question is a screener. They want to hear that the default is in-memory, that persistence comes from choosing `PersistentClient` with a path, that there is no `persist()` call to make in current versions, and ideally that `HttpClient` is the third option where a separate server owns the storage.

  • Where does PersistentClient write if you do not pass a path?
    It defaults to `./chroma`, a directory relative to the process's working directory. That is fine for a script run from a fixed location, but it is a common surprise inside containers or services started from a different directory — the store appears empty because a new directory was created somewhere else. Pass an absolute path in anything deployed.
  • Is there any way to snapshot an EphemeralClient's data before the process exits?
    Not through a built-in export — Chroma has no dump command for an in-memory client. You would have to read the data back out with `get(include=["embeddings", "documents", "metadatas"])` and re-add it to a `PersistentClient`. If you might need the data later, start with a persistent client instead.
  • What does client.reset() do and why does it usually fail?
    It deletes all collections and data. By default it raises, because resetting is only allowed when the client was constructed with `allow_reset=True` in its settings (or the equivalent server setting). The guard exists so an accidental call cannot destroy a production store; enable it in test fixtures only.

saying these in an interview costs you the question

  • Claiming chromadb.Client() persists to disk by default
  • Saying you must call client.persist() to save data
  • Thinking PersistentClient uploads data to a Chroma cloud service
  • Assuming switching to HttpClient migrates existing local data automatically
  • Believing the collection API differs between ephemeral and persistent clients

context

open as a page

What breaks when two processes open the same Chroma PersistentClient path?

level: seniorimportance: must knowfreq 50%

basics

~20 s

A persistent Chroma client is embedded, so each process gets its own SQLite handle and its own in-memory copy of the vector index. Writes by one process are invisible to the other's loaded index, and concurrent writers hit SQLite locking. Run the Chroma server and use HttpClient instead.

open as a page

What does Chroma write inside a PersistentClient path directory on disk?

level: middleimportance: should knowfreq 52%

basics

~20 s

A chroma.sqlite3 file holds collections, ids, documents, metadata and the embedding records; alongside it sit UUID-named subdirectories, one per vector segment, containing the binary HNSW index files. Both parts belong to one database and must be copied together.

open as a page

How do you run Chroma as a server and connect clients to it?

level: middleimportance: should knowfreq 45%

basics

~20 s

Start the server with chroma run --path ./chroma_data --host 0.0.0.0 --port 8000, or run the chromadb/chroma container with its data directory on a mounted volume. Applications then use chromadb.HttpClient(host=..., port=...) and call heartbeat() to verify connectivity.

open as a page

How do you back up and move a Chroma persistent store between machines?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Chroma has no online backup command, so you quiesce writes or stop the process, copy the whole data directory atomically (SQLite file plus index directories), and restore it into the same or a newer Chroma version. Copying a live directory risks an inconsistent snapshot.

open as a page

When are Chroma's tenants and databases enough to isolate multiple customers?

level: principalimportance: nice to knowfreq 26%

basics

~20 s

Tenants and databases are namespacing, not isolation: they scope collection names inside one store but share the same process, memory, disk and index resources. They suit internal separation of environments or teams, not untrusted customers needing enforced boundaries or independent capacity.

open as a page