Most teams pick a database target the wrong way: they line up engine feature matrices and compare replication modes, partitioning, and JSON support column by column. That produces a defensible-looking shortlist and tells you almost nothing about whether the move will succeed, because a database migration is not won or lost on the engine’s features. It is won or lost on how much of your application logic has to be rewritten and validated. The better approach is to fix a short list of factors that genuinely change the answer, score your real estate against them, and only then look at engines. This guide gives you that rubric.
Start with the facts, not the feature list
Before you shortlist anything, write down four things about what you actually run. First, the surface area of procedural code: the count and complexity of stored procedures, packages, triggers, and functions in Oracle PL/SQL, SQL Server T-SQL, or Db2 SQL PL, because that is the long pole of the whole project. Second, how much application-SQL you can realistically change: vendor hints, DUAL, ROWNUM, proprietary functions, and outer-join syntax all live in the app, not the database. Third, your read and write profile and scale: OLTP concurrency, analytical queries, data volume, and growth. Fourth, the SQL skills already on your team. Those four facts decide more than any feature checkbox.
What actually drives the effort
- Procedural-code surface area. The volume and difficulty of stored logic is the single biggest driver of effort. A schema with thin logic ports quickly; one built around large PL/SQL packages does not, and that alone can favor a high-compatibility path over a clean-break one.
- Application-rewrite tolerance. Some applications you can freely change; some are vendor-shipped or frozen. The less you can touch the app, the more you value dialect compatibility over a pristine target.
- Managed versus self-hosted. Decide whether you want to keep running the database yourself or hand operations to a provider. This is an operating-model choice as much as a cost one, and it narrows the field before engine features do.
- Read and write patterns and scale. Complex analytical and procedural workloads, high write concurrency, and sheer data volume push you toward engines that handle them natively rather than ones you bolt scale onto later.
- In-house SQL skills. An engine your team already knows is cheaper to run than a theoretically better one they will learn under fire. Be honest about who administers and tunes it at 2am.
- Compliance and data residency. Regulatory, residency, and audit constraints can rule out a managed cloud service outright, or dictate which regions and which self-hosted options are even eligible.
Which engine fits which estate
Score your estate against the criteria above, then treat these as starting points rather than conclusions. Most commercial-database exits land on PostgreSQL: it carries no license fee, has the extension ecosystem and enterprise features to cover the majority of Oracle, SQL Server, and Db2 workloads, and rewards teams willing to own their own operations. If you want that same PostgreSQL destination but would rather hand day-to-day operations to a provider, Amazon Aurora trades usage-based pricing and cloud lock-in for managed durability, and its PostgreSQL-compatible edition converts the same way self-managed PostgreSQL does. Estates that are high-volume but relatively simple OLTP, or applications already built around that ecosystem, look first at MySQL or MariaDB, with the caveat that they are weaker on complex procedural and analytical SQL. The right engine falls out of your scores, not out of any engine’s popularity.
Where database ports break schedules
A few errors recur. The first is estimating the project from the data size when the data movement is the easy part and the procedural code is where schedules break: read the assessment report your conversion tool produces before you commit to a date. The second is choosing the engine on its feature matrix while ignoring how much application SQL is hardcoded to the incumbent’s dialect, which is where a “simple port” becomes an application rewrite. The third is treating a document store like MongoDB as a dialect swap when re-modeling documents into relational tables or JSONB is a re-platforming with a rewritten query layer. A quieter fourth: not pricing the incumbent’s actual renewal, so you compare targets against a guess instead of the number you are trying to beat.
Proving the target before you commit
Turn your top candidate into a rehearsal with written acceptance criteria. Convert and load the schema, migrate the procedural code, and run a genuine parallel run: replay representative read and write workloads against both databases, then compare results, row counts, checksums, and query plans, not just whether queries return. Promote only when the target meets documented correctness and performance criteria under realistic load, and keep the source recoverable through cutover. Model the multi-year cost on your own vCPU count and edition with the calculator, and treat the figures as illustrative until a vendor or partner quotes your specific configuration. Choose the engine that clears your acceptance bar at an operational load your team can carry, not the one with the longest feature list.