The tiers
memloom’s storage is an adapter, and the same schema and SQL run on both implementations:
The embedded tier is the right default: there is nothing to set up or run, and backup is
copying a folder.
Reach for the server tier when you want concurrent DB access (the PGLite single-connection
lock is the thing you feel), a store bigger than comfortable in one folder, or a store shared
across machines.
Backing up the embedded store
The whole store lives in the data folder. Stop the daemon first so the data directory is quiescent:config.env travels separately (same folder, one file).
Running against Docker Postgres
1. Start Postgres with pgvector:~/.memloom/config.env:
memloom serve. The daemon connects with a pooled pg adapter instead of opening the
PGLite folder, and the first init() creates the full schema on an empty database, so there
is no separate provisioning step. Everything else (CLI, MCP, viewer, memloom reembed) reads
the same config and follows. Two differences from the embedded tier: the data-dir lock is not
used (the Postgres server handles concurrency), and the daemon does not start the wire-protocol
bridge on 54329 (inspect the server directly with any Postgres client).
Embedding memloom as a library instead? The same tier is one constructor argument:
pg is an optional dependency: run pnpm add pg in the project that runs this.
Migrating existing data
Two paths, depending on how much history you care about: Re-ingest (simple, loses history). Point the new store at the same embedding config and replay your sources:context add your files again, re-save what matters. Version chains and
resolved conflicts don’t come along. For a store that’s mostly ingested documents, this is
usually all you need: documents are mirrors, and re-ingesting reproduces them exactly.
Copy the rows (full fidelity). The daemon speaks the Postgres wire protocol on
127.0.0.1:54329, so with the daemon running you can pull data out with standard tools and
load it into the Docker database:
memloom serve once with MEMLOOM_PG_URL pointed at
the Docker database; it creates the schema), then load data-only. The wire server is a single-connection bridge into PGLite. If pg_dump
trips over it, fall back to per-table COPY ... TO STDOUT via psql, in dependency order:
_memloom_meta, memory_objects, memory_schema, memory_entities, memory_edges,
memory_dedup_decisions, context_documents, context_chunks, memory_index_runs,
memory_index_events, assistant_sessions, assistant_messages. Skipping the later ones
silently drops your schema vocabulary, indexing history, and assistant chats.
What stays local no matter what
Whichever tier you run, the trust model doesn’t change: the HTTP API binds to127.0.0.1,
CORS admits only localhost origins, and the only outbound traffic is to the embedding/LLM
provider you configured. Self-hosting the database in Docker doesn’t expose memloom to the
network unless you publish the ports yourself.