Migrate and continuously sync databases between MySQL and Postgres in all four directions — initial snapshot, CDC catch-up, and operator-driven cutover in one tool, opinionated about correctness. SQLite files and live Cloudflare D1 databases import into Postgres or MySQL too, and SQLite is also a migrate target.
go install sluicesync.dev/sluice/cmd/sluice@latest
sluice sync start — MySQL → Postgres, live. See every command in action →
Schema-evolution, cutover-priming, and slot-health capabilities usually found only in commercial/enterprise CDC tools — Apache 2.0, a single static binary, no daemon, no SaaS dependency.
MySQL → Postgres, Postgres → MySQL, and same-engine in both directions. PlanetScale and self-hosted Vitess flavors included.
Import a SQLite file or a wrangler d1 export .sql dump (--source-driver sqlite), or read a live D1 over its HTTP query API (--source-driver d1), into Postgres or MySQL — big integers above 253 round-trip exactly. SQLite is also a migrate target; sqlite-trigger / d1-trigger add trigger-based continuous sync.
Move a whole MySQL server's databases or a Postgres source's schemas in one run with --all-databases / --all-schemas (each to a same-named, auto-created target namespace), or fan into one schema with --target-schema — on both migrate and sync start.
Cross-region / PlanetScale-MySQL CDC apply folds consecutive same-shape INSERTs into one multi-row statement and coalesces UPDATE / DELETE batches, turning N round trips into one so high-latency apply keeps up.
Managed Postgres that blocks logical replication (e.g. Heroku) still streams via a trigger-based CDC engine — no replication slot or REPLICATION role required.
ADD COLUMN forwards automatically; every other shape refuses loudly with a structured drift diff naming the column that changed.
Pre-emptive slot-health warnings, a source-side heartbeat writer, and a Prometheus /metrics + /readyz endpoint for k8s health checks.
sluice cutover primes sequences so the first post-cutover INSERT can't collide on the primary key.
Every silent-loss class has a structured refuse-loudly message with an operator-action recovery hint. Paste it into Slack and the on-call DBA knows what to fix.
Install the binary, then run a one-shot migration or start a resumable continuous sync.
# Install go install sluicesync.dev/sluice/cmd/sluice@latest # One-shot migration: MySQL → Postgres sluice migrate \ --source-driver mysql --source 'root:rootpw@tcp(localhost:3306)/app' \ --target-driver postgres --target 'postgres://postgres:pgpw@localhost:5432/app?sslmode=disable' # Continuous sync: snapshot + CDC catch-up, resumable on restart sluice sync start \ --source-driver mysql --source ... \ --target-driver postgres --target ... \ --stream-id myapp-prod # Cutover-time sequence priming (post-snapshot, pre-traffic-switch) sluice cutover --config sluice.yaml --cutover-sequence-margin=1000 # Import a SQLite file (or a `wrangler d1 export` .sql dump) → Postgres sluice migrate \ --source-driver sqlite --source ./app.db \ --target-driver postgres --target 'postgres://...?sslmode=disable' # Import a LIVE Cloudflare D1 → Postgres (token via CLOUDFLARE_API_TOKEN) sluice migrate \ --source-driver d1 --source 'd1://<account_id>/<database_id>' \ --target-driver postgres --target 'postgres://...?sslmode=disable'
sluice is built around three product surfaces — use one, or all three end to end.
Read source schema, create target tables, bulk-copy rows, then build indexes and constraints — deferred for fast copy, resumable per-table. Many databases / schemas in one run, including SQLite files and live Cloudflare D1.
Snapshot → CDC handoff with resumable checkpoints, schema-drift detection, and slot-health telemetry against quiet sources.
Long-running sync behind /healthz, /readyz, and /metrics, or one-shot jobs in CI and CronJobs via the container image.