Postgres and Milvus
SQLite remains the simplest local backend. Use this guide when you need to exercise the Postgres runtime or move a Postgres deployment's vector storage from pgvector to Milvus.
Start local Postgres
Basic Memory's Postgres backend requires the pgvector extension even when Milvus will own semantic vectors. Create docker-compose-postgres.yml with the same local service used by the Basic Memory repository:
services:
postgres:
image: pgvector/pgvector:pg17
container_name: basic-memory-postgres
environment:
POSTGRES_DB: basic_memory
POSTGRES_USER: basic_memory_user
POSTGRES_PASSWORD: dev_password
ports:
- "5433:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U basic_memory_user -d basic_memory"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
Start the database:
docker compose -f docker-compose-postgres.yml up -d
docker compose -f docker-compose-postgres.yml ps
Point Basic Memory at it before starting the MCP server or running a CLI command:
export BASIC_MEMORY_DATABASE_BACKEND=postgres
export BASIC_MEMORY_DATABASE_URL='postgresql+asyncpg://basic_memory_user:dev_password@localhost:5433/basic_memory'
bm status
The first startup applies migrations and seeds the default project automatically. The credentials above are for a private local development database only; choose real credentials and network controls for any shared deployment.
postgres:17 does not include pgvector. Use the pgvector/pgvector:pg17 image or run CREATE EXTENSION IF NOT EXISTS vector; on an existing Postgres server before Basic Memory migrates it.Use the default pgvector index
Postgres uses pgvector unless you change semantic_vector_index. Build embeddings for already indexed notes with:
bm reindex --embeddings
SQLite ignores semantic_vector_index and continues to use sqlite-vec.
Install Milvus support
Install Basic Memory with the optional Milvus dependency:
uv tool install 'basic-memory[milvus]'
pip install 'basic-memory[milvus]'
The extra supports Milvus Lite on macOS and Linux and remote Milvus or Zilliz Cloud on every supported platform. Windows cannot run Milvus Lite but can connect to a remote deployment.
Configure Milvus Lite
Create the parent directory first, then use an absolute URI ending in .db:
mkdir -p "$PWD/.basic-memory-milvus"
bm config set semantic_vector_index milvus
bm config set milvus_uri "$PWD/.basic-memory-milvus/basic-memory.db"
Despite the suffix, Milvus Lite creates a directory tree at that path, including collections/, databases/, and LOCK; it does not create one database file. Pymilvus rejects a URI without the .db suffix or a URI whose parent directory does not already exist.
milvus_database is ignored by Milvus Lite because Lite does not support named databases. Leave its default value in place.
Connect remote Milvus or Zilliz
bm config set semantic_vector_index milvus
bm config set milvus_uri http://localhost:19530
bm config set milvus_token root:Milvus
For Zilliz Cloud, set its endpoint and token instead. milvus_timeout_seconds applies to every client operation and defaults to 30 seconds. Collections reload across processes, so a restart reuses an existing compatible collection.
Reindex after every index switch
Run an incremental embedding rebuild immediately after changing semantic_vector_index:
bm reindex --embeddings
The incremental rebuild is sufficient; --full is not required. Until the configured index has ready rows:
- vector search returns no results;
- hybrid search quietly serves full-text results only; and
bm reindex --embeddingsreports which index it populated and exits nonzero on failure.
Hands-on verification found identical vector rankings and scores to four decimal places across sqlite-vec, pgvector, and Milvus Lite on the same corpus. Basic Memory also refuses dimension mismatches, reports a missing Milvus extra directly, honors the configured timeout, and reloads collections after restart.
Switch indexes safely
Vector-index ownership is fail-closed. If a switch or switch-back finds manifest rows owned by another index, Basic Memory refuses to mutate them instead of guessing which vector store is authoritative.
- Restore the previously configured index if a premature switch raises
SemanticVectorIndexExtensionError. - Remove the current index's project-scoped vectors and the corresponding vector-manifest rows while that index is still configured.
- Change
semantic_vector_index. - Run
bm reindex --embeddingsand confirm it exits successfully.
There is no general cleanup command yet. Treat manual vector-store and manifest cleanup as an operator procedure and back up the database first.
search_vector_embeddings projection. They are not used by the Milvus search path, but they continue to consume disk until you remove them manually. Do not delete them until the Milvus rebuild is successful and you have decided not to switch back using that projection.Stop local Postgres
docker compose -f docker-compose-postgres.yml down
Add --volumes only when you intentionally want to delete the local database volume.
Related pages
- Semantic Search — retrieval modes, reranking, and reindex behavior.
- Configuration — all Postgres, Milvus, and embedding settings.
- Upgrade to v0.23 — breaking changes and migration notes.

