yeke.io · docs

SQLite to PostgreSQL Migration

Move SQLite data to PostgreSQL with yeke-migrate. The tool runs while core is stopped, supports this direction only and verifies data integrity before marking the migration complete.

Overview

Move to PostgreSQL without throwing away your audit trail.

yeke-migrate copies records from a SQLite file into PostgreSQL, including the audit trail and encrypted columns. It does not delete the source file.

The tool is offline and one-way: it runs while core is stopped, and only moves data SQLite → PostgreSQL. There is no reverse direction (PostgreSQL → SQLite).

Prerequisites

None of the three are enforced by the tool; they are operational discipline.

  • Back up first. Before starting, take a copy of the source SQLite file (and the adjacent snapshot.key file) — that copy is your way back.
  • Core must be stopped. Nothing should be writing to the source file; the tool does not enforce this itself; stopping the core process before running it is the operator's responsibility.
  • The target must be empty. If the target PostgreSQL already has a schema_migrations table, the tool refuses to run — recovering from a half-finished attempt means dropping the target schema and starting over from the source's pre-migration backup.

Getting the tool

It is not distributed separately; it ships inside the core image.

yeke-migrate ships inside the core image as a single-file bundle (/app/tools/yeke-migrate.mjs). For a regular install you can extract it from the published image and run it on any machine with Node.js ≥ 22:

docker create --name yeke-migrate-extract nairotech/yeke:<version>
docker cp yeke-migrate-extract:/app/tools/yeke-migrate.mjs ./yeke-migrate.mjs
docker rm yeke-migrate-extract

The air-gap package ships the same tool as a ready bundle (cli/yeke-migrate-<version>.mjs) — see the air-gap installation page, step 5.

Usage

Two required flags.

On the installation page's default path, the source file sits inside a Docker volume, so there's no path to it on the host; take it out first with core stopped (snapshot.key comes along with it). If you mounted your own directory instead, skip this step — point --source straight at core.db in that directory.

docker stop yeke
docker cp yeke:/var/lib/yeke ./yeke-data
node yeke-migrate.mjs \
    --source ./yeke-data/core.db \
    --target postgres://user:pass@host:5432/yeke

The key that opens the envelope-encrypted columns is resolved in the same order as core's own key resolution: --snapshot-key > --snapshot-key-file > YEKE_SNAPSHOT_KEY > YEKE_SNAPSHOT_KEY_FILE > the snapshot.key file next to the source. If you don't supply the same key that encrypted the source, the envelope-sample-open verification step fails and the tool leaves the target unmarked as complete.

The target schema is not reinvented by the tool — it derives from core's own current baseline schema, and the table-copy order follows the same dependency graph. counters and operation_events.seq values are copied as-is, not recomputed.

Integrity verification

Part of the tool, not an afterthought.

  • Row-count equality. Source and target row counts are compared per table.
  • Audit trail integrity. MAX(seq) in operation_events plus a byte comparison of a random sample.
  • Envelope sample decryption. A sample of encrypted columns is decrypted with the migrated key to confirm it actually opens.
  • SIEM export cursors. If configured, the chain_head/cursor rows of any audit-export targets are checked for an exact copy.

Until all of these pass, the tool does not write the "complete" row to schema_migrations on the target.

A half-finished migration

An interrupted migration is never silently assumed to have succeeded.

If migration is interrupted or verification fails, the target’s schema_migrations table has no completion record. Core refuses to start in PostgreSQL mode against that incomplete target.

CodeMeaning
0Complete, target marked.
1Integrity verification failed — target not marked.
2Usage error (missing/invalid argument).
3Target not empty — the tool's own safety gate.

Limits

The tool is kept narrow, not a general-purpose migration framework.

  • No reverse direction. PostgreSQL → SQLite is not supported. Moving data out of an HA install back down to a single node uses PostgreSQL's own tools (pg_dump).
  • Back up first. Migration does not corrupt the source, but an interruption or failure with no backup of the source makes going back impossible.
  • No live/dual-write migration. Core must not be running while migration happens; expect downtime, the same class of interruption every deploy already causes.
  • No resume semantics. Recovering from an interrupted attempt means dropping the target and starting over.

How is the target PostgreSQL set up?

Before migrating, know the target's connection shape and license gate: both are on the PostgreSQL connection page.