Backends & configuration

August 18, 2026 · View on GitHub

memgres has two independent, env-driven axes. Change either without touching code or data model — only re-embedding requires care (the schema stamps the model, so a mismatch hard-fails instead of silently returning garbage).

  1. Embedding providerhow vectors are computed (or not, for lexical-only).
  2. Vector backendwhere vectors are stored & ranked (Postgres or Qdrant).

1. Embedding providers (MEMGRES_EMBED_PROVIDER)

Choosing between a local and a cloud model, and the operational gotchas (dimension drift, context-window truncation, offline caches)? See the dedicated guide: EMBEDDINGS.md. The table below is the quick reference.

ProviderVectors fromNeedsNotes
none (default)nothingLexical FTS only; no model, API, or GPU.
localsentence-transformers in-process[local] extraRuns on CPU/GPU; dimension inferred from the model.
openaiOpenAI cloudAPI keytext-embedding-3-small etc.
jinaJina cloudAPI keySends passage/query task hints.
openai-compatibleany OpenAI-shaped /embeddings serverbase URLLM Studio, Ollama, vLLM, TEI, LocalAI… key optional.

Shared settings: MEMGRES_EMBED_MODEL (model id), MEMGRES_EMBED_DIM (required for every HTTP provider; local infers it), MEMGRES_EMBED_API_KEY, MEMGRES_EMBED_API_BASE (server URL).

Switching local ↔ cloud ↔ self-hosted is one variable — MEMGRES_EMBED_PROVIDER. Changing the model or dimension after data exists means the stored vectors no longer match; re-embed into a fresh collection (the schema guard will stop you from mixing them by accident).

Examples

Lexical only — no embeddings (default):

MEMGRES_EMBED_PROVIDER=none
# recall works via Postgres full-text search; mode=semantic/hybrid unavailable

Local (sentence-transformers)pip install "…[local]":

MEMGRES_EMBED_PROVIDER=local
MEMGRES_EMBED_MODEL=sentence-transformers/all-MiniLM-L6-v2
# MEMGRES_EMBED_DIM is inferred from the model

OpenAI cloud:

MEMGRES_EMBED_PROVIDER=openai
MEMGRES_EMBED_MODEL=text-embedding-3-small
MEMGRES_EMBED_DIM=1536
MEMGRES_EMBED_API_KEY=sk-...

LM Studio (OpenAI-compatible, local server, no key):

MEMGRES_EMBED_PROVIDER=openai-compatible
MEMGRES_EMBED_API_BASE=http://localhost:1234/v1
MEMGRES_EMBED_MODEL=<the model you loaded in LM Studio>
MEMGRES_EMBED_DIM=768

Ollama (OpenAI-compatible endpoint):

MEMGRES_EMBED_PROVIDER=openai-compatible
MEMGRES_EMBED_API_BASE=http://localhost:11434/v1
MEMGRES_EMBED_MODEL=nomic-embed-text
MEMGRES_EMBED_DIM=768

Jina cloud:

MEMGRES_EMBED_PROVIDER=jina
MEMGRES_EMBED_MODEL=jina-embeddings-v3
MEMGRES_EMBED_DIM=1024
MEMGRES_EMBED_API_KEY=jina_...

2. Vector backend (MEMGRES_VECTOR_BACKEND)

Only relevant once an embedding provider is set (lexical-only needs no vector store).

BackendWhere vectors liveWhen to pick
pgvector (default)in the memory table, same Postgresone datastore, one backup; simplest.
qdranta separate Qdrant serviceyou already run Qdrant, or want a dedicated ANN service.

How Qdrant mode splits the work: Qdrant stores only the vector + the memory's namespace and ranks by cosine similarity; Postgres stays the source of truth for bodies and for every other filter (tags, subtree, TTL). Semantic recall ranks in Qdrant, then fetches and filters the candidates in Postgres. So tag/tree/TTL edits never touch Qdrant — only a body change re-embeds (upsert) and forget deletes the point.

pgvector (default)

MEMGRES_VECTOR_BACKEND=pgvector      # nothing else to run

Qdrant

MEMGRES_VECTOR_BACKEND=qdrant
QDRANT_URL=http://localhost:6333
QDRANT_API_KEY=                      # if your Qdrant requires one
MEMGRES_QDRANT_COLLECTION=memgres    # default
MEMGRES_QDRANT_CA=                   # path to a CA/self-signed cert (only for https)

MEMGRES_QDRANT_CA is only for an https:// Qdrant whose certificate the system trust store doesn't already know — a self-signed or private-CA deployment. Point it at the PEM and the client verifies against exactly that cert; leave it unset for plain http or a publicly-trusted certificate. Reusing a Qdrant you already run? Give memgres its own MEMGRES_QDRANT_COLLECTION — a collection is the isolation unit, so your other collections are untouched, and within it every point is tagged by namespace for tenant-scoped search. The chunk vectors (the semantic index) live in a sibling <collection>_segments collection — same isolation, cleaned up alongside the memory. (Upgrading from a pre-0.4 deployment? The old <collection> held one vector per memory and is no longer used — drop it; the chunks are rebuilt into <collection>_segments on first run.)

With docker compose, start Qdrant alongside the service:

docker compose --profile qdrant up

(The compose file points the service at http://qdrant:6333 automatically.)


Putting it together — full example configs

Single-user, semantic, everything in one Postgres (local model):

MEMGRES_DATABASE_URL=postgresql://memgres:memgres@localhost:5432/memgres
MEMGRES_EMBED_PROVIDER=local
MEMGRES_EMBED_MODEL=sentence-transformers/all-MiniLM-L6-v2
MEMGRES_VECTOR_BACKEND=pgvector

Multi-tenant service, cloud embeddings, dedicated Qdrant:

MEMGRES_DATABASE_URL=postgresql://…
MEMGRES_KEY_MODE=managed
MEMGRES_EMBED_PROVIDER=openai
MEMGRES_EMBED_MODEL=text-embedding-3-small
MEMGRES_EMBED_DIM=1536
MEMGRES_EMBED_API_KEY=sk-...
MEMGRES_VECTOR_BACKEND=qdrant
QDRANT_URL=https://your-qdrant:6333
QDRANT_API_KEY=...

Air-gapped / offline, self-hosted model, lexical + semantic in Postgres:

MEMGRES_EMBED_PROVIDER=openai-compatible
MEMGRES_EMBED_API_BASE=http://lmstudio:1234/v1
MEMGRES_EMBED_MODEL=<local model>
MEMGRES_EMBED_DIM=768
MEMGRES_VECTOR_BACKEND=pgvector

See .env.example for the complete list of settings.