pgferry.com — Migrate MySQL, MariaDB, SQLite, or MSSQL databases to PostgreSQL with a plan-first workflow, copy-pasteable configs, and explicit handling for the messy parts.
Introspects your source schema, creates matching PostgreSQL tables, streams data with COPY, then adds keys, indexes, foreign keys, sequences, and triggers after the load. When things get messy, you still get hooks, type mapping, checkpoints, validation, and post-load cleanup.
- No runtime dependencies or extra tooling to install
- Interactive
pgferry wizardthat can generate, plan, and start a migration in one flow - Fast parallel
COPYloads with range-based chunking for large tables - Clear stage and row-copy progress logs, so long runs do not look frozen
- Preflight
plancommand reports views, routines, triggers, scheduled events, generated columns, skipped indexes, semantic-drift warnings (defaults, CHECK constraints, and — where the source has them — comments and partitioning), orphan-cleanup candidates, required extensions, collation warnings, and (with copy-risk analysis) a low-confidence copy-phase ETA range before PostgreSQL is touched - Resumable chunked migrations, so failures do not send you back to zero
- Consistent-snapshot mode for migrating live source databases safely
- Built for messy real-world schemas with hooks, orphan cleanup, generated-column reporting, and unsupported-index warnings
schema_onlyanddata_onlyruns when you need tighter control- Extension-backed features like
citextand PostGIS, with validation and optional auto-create - Post-load validation modes that range from fast
row_countchecks to stronger boundedsampled_hashcontent checks
CI runs integration tests across MySQL 5.7, 8.0 and latest, MariaDB 10.6 and latest, MSSQL 2017 through 2025, and SQLite against the latest PostgreSQL release on every commit.
On macOS and Linux, install with Homebrew from the Limetric tap:
brew install Limetric/tap/pgferry
pgferry versionDownload the latest binary from GitHub Releases.
git clone https://github.com/Limetric/pgferry.git
cd pgferry
go build -o build/pgferry .For a first run, the wizard is all you need:
pgferry wizardIt walks you through the source and target DSNs, target schema, migration mode, and the key type-mapping options. It then runs plan and lets you start the migration in the same flow. In an interactive terminal, plain pgferry also opens the wizard.
To run the generated config through those steps yourself:
pgferry plan migration.toml
pgferry migrate migration.tomlIf you prefer to create the config yourself, the minimum shape looks like this:
schema = "app"
[source]
type = "mysql"
dsn = "root:root@tcp(127.0.0.1:3306)/source_db"
# type = "mariadb"
# dsn = "root:root@tcp(127.0.0.1:3306)/source_db"
# type = "sqlite"
# dsn = "/path/to/source.db"
# type = "mssql"
# dsn = "sqlserver://sa:pass@127.0.0.1:1433?database=source_db"
[target]
dsn = "postgres://postgres:postgres@127.0.0.1:5432/target_db?sslmode=disable"Any PostgreSQL sslmode is supported. sslmode=disable is just a local example.
If you want to keep secrets out of the committed TOML, set them at runtime instead:
export PGFERRY_SOURCE_DSN='root:root@tcp(127.0.0.1:3306)/source_db'
export PGFERRY_TARGET_DSN='postgres://postgres:postgres@127.0.0.1:5432/target_db?sslmode=disable'
pgferry migrate migration.tomlNon-empty PGFERRY_SOURCE_DSN and PGFERRY_TARGET_DSN override source.dsn and target.dsn.
Use the docs site for copy-pasteable example configs and walkthroughs:
The raw example files still live in examples/.
The website is the primary end-user docs surface:
- Install
- Quick Start
- Advanced Options
- Migration Patterns
- Guides
- Examples
- Operations
- Operator tuning
- Reference
Most of this codebase was written with LLM agents. The architecture, edge case handling, and test coverage reflect that. It runs in production and the integration test matrix catches regressions, but you should know how it was made.
Apache 2.0. See LICENSE.