Command reference
Every sluice command, its purpose, the flags that matter most, and worked examples.
The general shape is sluice <command> [flags]. Every command accepts the
global flags (--config, --log-level, …).
Run sluice <command> --help for the complete flag list — the tables below cover the
flags you'll reach for most.
engines
sluice engines
List the database engines built into this binary and their bulk-load / CDC capabilities.
sluice enginesmigrate
sluice migrate
Run a one-time schema + data migration: translate the schema, create tables, bulk-copy rows, then build indexes and constraints.
| Flag | Purpose |
|---|---|
--source-driver / --source | Source engine name and DSN (or SLUICE_SOURCE). |
--target-driver / --target | Target engine name and DSN (or SLUICE_TARGET). |
--dry-run, -n | Print the plan; don't touch the target. |
--include-table / --exclude-table | Glob-aware table filters (mutually exclusive). Scope the bulk copy — including the PlanetScale (VStream) snapshot — not just the write path. |
--resume, -r | Resume a failed migration from per-table checkpoints on the target. |
--bulk-parallelism | Parallel reader/writer pairs per large table (0 = auto). |
--table-parallelism | Tables copied concurrently (0 = auto). Multiplies with --bulk-parallelism; the product is bounded by the target connection budget. |
--max-target-connections | Connection budget on the target the parallelism product must fit inside. |
--index-build-parallelism | Postgres-only: deferred indexes built concurrently after the bulk copy. |
--type-override | TABLE.COLUMN=TYPE — force a target column type (repeatable). |
--redact | Redact a PII column, e.g. users.email=hash:sha256 (repeatable). |
--target-schema | Postgres-only: land tables under a named schema namespace. |
--reset-target-data | Destructive recovery: drop source-schema tables on the target, then cold-start. Prompts unless --yes. |
Filtered dry run, then apply:
sluice migrate --source-driver mysql --source ... --target-driver postgres --target ... \
--include-table 'app_*' --exclude-table 'app_audit' --dry-run
Redact PII as it copies:
sluice migrate --source-driver mysql --source ... --target-driver postgres --target ... \
--redact users.email=hash:sha256 \
--redact users.ssn=mask:ssn
PRIMARY KEY but a NOT-NULL UNIQUE key now migrates and syncs MySQL→Postgres without a manual schema change — sluice promotes the unique key for an idempotent copy (this already worked MySQL→MySQL). A table with no PK and no NOT-NULL unique key is still refused loudly.sync start
sluice sync start
Start (or resume) a continuous-sync stream: consistent snapshot → bulk copy → ongoing CDC. Identified by --stream-id for clean restart.
| Flag | Purpose |
|---|---|
--stream-id | Stream identifier; the key its position is persisted under on the target. |
--slot-name | Postgres replication-slot suffix (default sluice_slot); set per-instance to run several streams off one source. |
--apply-batch-size | CDC changes per target tx, or auto. Default 1 (conservative); higher engages the AIMD latency controller. |
--metrics-listen | Bind a Prometheus /metrics + /readyz endpoint, e.g. :9090. |
--source-heartbeat-interval | Write a heartbeat row on the source every interval so the slot/binlog can't be evicted past the consumer against an idle source. |
--dry-run, -n | Show cold-start vs warm-resume and the planned actions without starting. |
--schema-already-applied | Skip all cold-start DDL (you promise the target catalog matches). For Atlas/Liquibase-managed or PlanetScale Safe-Migrations targets. |
--include-table / --exclude-table | Glob-aware table filters (mutually exclusive). Scope the cold-start snapshot and its resume — including the PlanetScale (VStream) snapshot, so an excluded table in a large keyspace is never streamed (v0.99.12–v0.99.13), not just the write path. |
--force-cold-start | Skip the pre-flight check that refuses to bulk-copy into a populated target. Use with caution — an INSERT into a non-empty table can collide on the primary key. Still warm-resumes from a persisted position (it only skips the check); ignored on the warm-resume path. |
--reset-target-data | Destructive recovery: delete the CDC-state row, DROP every source-schema table on the target, then run a fresh cold-start. For a wedged-state recovery (e.g. slot-missing fall-through). Prompts (type reset) unless --yes. See ADR-0023. |
--restart-from-scratch | Force a fresh cold-start re-copy from the beginning, ignoring any persisted resume position (incl. a mid-COPY cursor) — without dropping the target (the idempotent copy absorbs the overlap). For a bad checkpoint. Differs from --force-cold-start (keeps the position) and --reset-target-data (drops tables). (v0.99.10) |
Run as a service with metrics + idle-source heartbeat:
sluice sync start --source-driver postgres --source ... --target-driver mysql --target ... \
--stream-id reporting \
--metrics-listen :9090 \
--source-heartbeat-interval 30ssync status / stop / health
sluice sync status · stop · health
Inspect, gracefully stop, and health-check a running stream. All take --stream-id plus the target connection.
sync status— show the stream's persisted position and phase.sync stop— request the stream to drain in-flight changes and exit cleanly.sync health— probe freshness against thresholds and return a cron-friendly exit code (non-zero when stale).
sluice sync health --stream-id app-prod --target-driver postgres --target ... \
--max-lag 5m # exit non-zero if the stream is more than 5 minutes behindsync from-backup
sluice sync from-backup run · stop
Replay a backup chain into a target as a long-running broker — polls a chain root (S3/GCS/Azure/local) for new incrementals and applies them. No direct source↔target connectivity required.
sluice sync from-backup run \
--backup-target s3://my-bucket/app-chain \
--target-driver postgres --target ... \
--stream-id app-broker --poll-interval 30s
sluice sync from-backup stop --backup-target s3://my-bucket/app-chaincutover
sluice cutover
Two-phase sequence priming at cutover: re-read source sequence / AUTO_INCREMENT state and apply it to the target with a safety margin, so the first post-cutover INSERT can't collide on the primary key.
sluice cutover --config sluice.yaml --cutover-sequence-margin 1000
Run after the snapshot has caught up and just before switching application traffic to the target.
backup
sluice backup
Take and verify logical backups — full snapshots and incremental chains, optionally encrypted, to local FS or object storage.
| Subcommand | Purpose |
|---|---|
backup full | Take a full snapshot (chain root). |
backup incremental | Append an incremental onto the existing chain. |
backup stream run / stop | Run as a long-lived process appending incrementals at a rolling cadence; stop drains the in-flight rollover and exits cleanly. |
backup verify | Re-checksum every chunk in a chain and report mismatches. |
backup prune / compact | Retention: drop the oldest segments, or merge consecutive segments whose gaps fall within --merge-window. Compact splits a merge group at a rotation-boundary coverage gap instead of refusing the run (v0.99.41) — chains stopped while the source was idle stay compactable. |
| Flag | Purpose |
|---|---|
--output-dir / --target | Destination: a local directory, or a URL (s3://, gs://, azblob://, file:///). Mutually exclusive. |
--chain-slot | Postgres-only, on backup full: provision the persistent replication slot (named by --slot-name) as the snapshot anchor and ensure the publication, so backup incremental chains with zero gap and no manual slot setup. (v0.99.35) |
--table-parallelism | Tables read concurrently during the backup sweep (the read-side analog of pg_dump -j); 0 = auto. Postgres-only — engages with a shareable exported snapshot. (v0.99.39) |
--include-table / --exclude-table | Glob-aware table filters; scope the backup snapshot itself — including the PlanetScale (VStream) snapshot — so an excluded table in a large keyspace is never streamed (v0.99.13), not just what's written. |
sluice backup full --source-driver postgres --source ... --target s3://my-bucket/app-chain --chain-slot
sluice backup incremental --source-driver postgres --source ... --target s3://my-bucket/app-chain
NaN, ±Infinity) now ride the chunk codec exactly — one such row no longer makes a table un-backupable, and restores are bit-identical to pg_dump.restore
sluice restore
Restore a logical backup chain (full + every incremental up to the tail) into a target database.
| Flag | Purpose |
|---|---|
--from-dir / --from | Backup location: a local directory, or a URL (s3://, gs://, azblob://, file:///). Mutually exclusive. |
--table-parallelism | Tables bulk-applied concurrently (the write-side analog of pg_restore -j); 0 = auto, works on both engines; incremental change replay stays ordered. (v0.99.39) |
--target-schema | Postgres-only: land restored tables under a named schema namespace. |
sluice restore --from s3://my-bucket/app-chain \
--target-driver postgres --target ...
Pair with sync start --resume-from-backup to resume CDC from the chain's tail without re-bulking.
trigger setup
sluice trigger setup
Install (or remove) the postgres-trigger engine's source-side state — slot-less CDC for managed Postgres that blocks logical replication.
| Flag | Purpose |
|---|---|
--dsn | Source Postgres DSN to install the trigger state into. |
--tables | Tables to capture (default: all). |
--allow-polled-fingerprint | Permit the non-superuser polled path when event triggers aren't grantable (e.g. Heroku). |
--capture-payload | full (default) / changed / minimal — how much of each row the trigger records. |
sluice trigger setup --dsn 'postgres://user:pass@host:5432/app' --allow-polled-fingerprint
# then stream with the trigger engine:
sluice sync start --source-driver postgres-trigger --source ... --target-driver mysql --target ... --stream-id appschema preview / diff
sluice schema preview · diff
Inspect translation without moving data: print the target DDL sluice would emit, or diff a live target against what sluice would produce.
sluice schema preview --source-driver mysql --source ... --target-driver postgres
sluice schema diff --source-driver mysql --source ... --target-driver postgres --target ...verify
sluice verify
Compare data integrity between source and target — row counts by default, escalating to sampled or full per-row hashing.
| Flag | Purpose |
|---|---|
--depth | How thorough: counts vs sampled-row vs full hash comparison. |
--sample-rows-per-table / --sample-seed | Sampling size and a deterministic seed. |
--strict-hash | Require byte-identical per-row hashes. |
--format / --output | Report format and output destination (for CI gating). |
sluice verify --source-driver mysql --source ... --target-driver postgres --target ... --depth countsmatview refresh
sluice matview refresh
Refresh PostgreSQL materialized views on the target (PG-only). Handy as a scheduled job after a sync catches up.
sluice matview refresh --target-driver postgres --target ... --view reporting.daily_totalsslot list / drop
sluice slot list · drop
Manage source-side Postgres replication slots — list sluice-created slots, or drop an orphaned one left by an interrupted stream.
sluice slot list --source-driver postgres --source ...
sluice slot drop --source-driver postgres --source ... --slot-name sluice_slotdiagnose
sluice diagnose
Assemble an operator bundle (source/target capability + role state, debug-zip shape) to attach when filing an issue.
sluice diagnose --source-driver mysql --source ... --target-driver postgres --target ... --out ./sluice-diagnose.zip