OperationsUpgrade

Upgrade

In place

docker compose pull mnemosyne
docker compose up -d mnemosyne

A 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.5

Breaking schema changes

We avoid them. When we have to make one, the migration is split into three deploys following the PlanetScale playbook:

  1. Additive — new column / table created. Code reads from either old or new. No downtime.
  2. Dual write — code writes both. Background backfill populates the new column for old rows.
  3. 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 v2 memory_type onto its v3 primitive (fact, episode, or skill) 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-migrate CLI reads batches from the source public.memories table, maps them, and writes to the v3 tables via raw SQL with ON 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 write

CUP is beta — the deterministic mapper and keyset CLI runner are implemented but not yet battle-tested at scale.