Upgrade
In place
docker compose pull mnemosyne
docker compose up -d mnemosyneA dedicated migrate service (npx mnemo-migrate) applies any pending
migrations and must exit 0 before the new server starts. No client-visible
downtime if you run multiple replicas behind a load balancer.
Migration safety
Migrations are forward-only. The bundled .down.sql files in
packages/core/migrations/ exist for completeness, but rolling back is
intentionally a manual psql operation so you never accidentally drop
production memory.
-- packages/core/migrations/0050_mnemo_org_fact_view.down.sql
DROP VIEW IF EXISTS mnemo_org_fact_view;To roll back a deploy, redeploy the previous image and apply the relevant
.down.sql by hand if a schema change must be reversed:
docker compose up -d mnemosyne:v1.5Breaking schema changes
We avoid them. When we have to make one, the migration is split into three deploys following the PlanetScale playbook:
- Additive — new column / table created. Code reads from either old or new. No downtime.
- Dual write — code writes both. Background backfill populates the new column for old rows.
- Cleanup — old column dropped after a release window.
This is why migrations 0046 and 0047 look small individually — each is one step of a multi-deploy migration.
Version skew
Mnemosyne replicas in a rolling deploy can run different versions simultaneously. The wire format is backwards-compatible within a minor version, and we test the previous N-2 versions in CI.
When upgrade fails
The migration runner is transactional per file. If migration 0055 fails,
the database stays at 0054, the migrate service exits non-zero, and the
new replica never starts — your load balancer keeps routing to the old
replicas.
npx mnemo-migrate
# applies pending migrations; on failure it exits non-zero and halts
# 0055 failed: <error message>Fix the failing migration, push a patch, redeploy.
Migrating v2 → v3 (CUP)
The Cognitive Upgrade Protocol (@mnemosyne/cup) is a one-time, deterministic
ETL that migrates legacy v2 data into the v3 schema. Earlier deployments stored
everything as flat memories rows keyed by a memory_type string; v3 uses typed
cognitive primitives. CUP bridges the two.
- TypeMapper — a pure, rule-based mapper (
mapV2Memory/mapV2MemoryBatch) that maps each v2memory_typeonto its v3 primitive (fact,episode, orskill) and applies the import-time confidence policy so imported facts start appropriately uncertain. It is not an LLM classifier — it is fast, free, and reproducible. - Keyset ingestion — the
mnemo-migrateCLI reads batches from the sourcepublic.memoriestable, maps them, and writes to the v3 tables via raw SQL withON CONFLICT DO NOTHING, so the run is idempotent and re-runnable. The source database is only ever read, never modified.
# Source (v2) and target (v3) databases
export DATABASE_URL=postgres://user:pass@host:5432/mnemosyne_v2
export DATABASE_URL_V3=postgres://user:pass@host:5432/mnemosyne
mnemo-migrate --workspace <uuid> # full migration
mnemo-migrate --workspace <uuid> --batch-size 50 # tune batch size (default 100)
mnemo-migrate --workspace <uuid> --dry-run # map and count, do not writeCUP is beta — the deterministic mapper and keyset CLI runner are implemented but not yet battle-tested at scale.