How We Live-Certified All 49 Database Migration Paths
DBShifts Engineering
The team building the migration platform
DBShifts supports MySQL, MariaDB, PostgreSQL, SQL Server, Oracle, SQLite and MongoDB. That's 7 sources × 7 targets = 49 migration paths — and "supports" is a word that's easy to put on a landing page and hard to make true. Most migration tools verify two or three popular pairs and assume the type mapper covers the rest. We decided that nothing ships as supported until a live migration of that exact pair passes verification end-to-end.
The certification fixture
Every certification run starts by seeding the source engine with a fixture written in its native dialect: three tables covering a foreign-key relationship, an index, and a wide cert_types table holding every type group the engine supports — integers in all widths, unsigned variants, fixed-precision decimals, floats, CHAR/VARCHAR/TEXT, binary and BLOB, dates, times, timestamps with and without timezones, booleans, JSON, ENUM/SET, UUID, arrays, network types.
The rows matter as much as the columns. Each fixture includes:
- a typical row — the happy path,
- an all-NULL row — nullability survives the trip,
- an extremes row — BIGINT max, max decimal precision, year-1000 timestamps,
- a multi-byte row — CJK text, emoji, a 2 KB string,
- a zero/empty row — empty strings, zero dates, empty byte arrays.
The run
For each pair the harness drives the exact code path a production migration uses — introspection, schema conversion, batched transfer with FK deferral, index rebuild — then validates with per-table row counts and an order-independent, type-aware checksum of every row on both sides. Lossy type conversions and objects routed to manual review are captured into the report, so "passed" means counted, hashed, and accounted for.
$ certify_pairs --pairs all [34/49] oracle → mssql ... pass (1.9s) [35/49] oracle → sqlite ... pass (1.8s) ... 49/49 pairs passed
What the harness caught
The first full run passed 7 of 49 pairs. The other 42 failures decomposed into about twenty-five real bugs — silent truncation, dropped columns, poisoned connections, lossy float fetches — most of which would have been production data-loss incidents. (We wrote up the worst offenders in a separate post.) After fixing every cluster and re-running until green, the matrix went 49/49.
Why this matters for you
When you point DBShifts at an Oracle source and a SQLite target — the kind of pair nobody advertises — you're not the first to run it. A live migration of that exact combination, with edge-case data designed to break it, passed counts and checksums before the pair was enabled. That's the bar every pair has to clear, every time we change the engine.
Migrate with the platform behind these posts
All 49 engine pairs live-tested. Validation, rollback, and CDC built in.
Start Free Migration