Benchmark methodology
five converters, nine schemas, one live PostgreSQL 16

Everything behind the numbers on the pgrecon page: what ran, which versions, what each tool needed to run at all, and how to reproduce it. August 2026.

The question and the bar

Every converter claims to convert an Oracle schema. The benchmark asks one narrower question: when the tool's output is applied to a real PostgreSQL, statement by statement, how many statements does PostgreSQL itself reject? An error here is not a missing feature or a style complaint - it is a statement the target database refuses. That is the same bar a real migration hits in production, whether a tool warned about it or not.

A zero on that bar does not mean everything converts, and the number only means something next to how much was attempted; the coverage numbers are stated below with the same precision as the error counts.

The nine schemas

Source database: Oracle XE 21c (21.3), loaded with all nine schemas. Target: a stock postgres:16 container. No compatibility extensions installed unless a tool's own output requires one, in which case that is recorded below.

Tools and versions

ToolVersion / mode
pgrecon0.5.0, pgrecon convert from an offline dump
CYBERTEC ora_migratorcurrent release, August 2026, over oracle_fdw 2.9.0 (Oracle Instant Client 23)
Ora2Pgv25.0, TYPE=TABLE,VIEW,SEQUENCE,TRIGGER,FUNCTION,PROCEDURE,PACKAGE
EDB Migration Toolkit55.13.0, -offlineMigration, community PostgreSQL target
AWS Schema Conversion Toolcurrent build, August 2026, via its batch CLI (.scts scripts)

How errors were counted

Each tool's generated SQL was applied to a fresh database in the same PostgreSQL 16 with psql -qX and ON_ERROR_STOP off, so every statement gets its chance; the error count is the number of lines PostgreSQL answered with ERROR. Function bodies were applied with check_function_bodies on wherever the tool's own output did not override it. Where a tool emitted per-schema files they were applied in the tool's own recommended order.

Per-tool accommodations

Runs were kept as fair as each tool allows; everything a tool needed beyond its documentation is recorded here.

Results

ConverterStatements rejectedNotes
pgrecon 0.50 every decline a named residue line
CYBERTEC ora_migrator40 plus two whole-schema crashes
Ora2Pg v2577 49 on OE, 18 on the lab schema, 8 on RECON_TEST; clean on the simple estates
EDB MTK 55.13135 of 477 emitted statements; the low counts on package libraries are absence, not quality
AWS SCT481 clean on HR only; 214 on utPLSQL, 76 on Alexandria, 73 on PLJSON

Coverage, stated with the same precision: pgrecon converted 51 percent of all objects mechanically - above 90 percent on the business-shaped schemas, far below on the object-type and package showcases, which nothing converts mechanically. Every unconverted object is one line in the residue report with a reason. One hierarchical view was additionally verified row-for-row against the live Oracle running the original. pgrecon's numbers were re-verified at 0.5.0; the other tools' outputs were unchanged from their original runs.

Reproduce it

podman run -d --name oracle-xe -e ORACLE_PASSWORD=... gvenzl/oracle-xe:21
podman run -d --name pg-target -e POSTGRES_PASSWORD=... postgres:16
# install HR/OE/CO from db-sample-schemas v21.1, the four projects
# from their repositories, RECON_TEST from this repo's fixture
pip install pgrecon==0.5.0
pgrecon script            # extraction script; run per schema via sqlplus
pgrecon load dump_dir --db est.db
pgrecon convert --db est.db
psql -qX -f schema_pg.sql 2>&1 | grep -c ^ERROR

Run each competing tool per its own documentation against the same schemas, apply with the same psql invocation, count the same way. If a number here looks wrong, that is a fair reaction - reproduce it and say so on the issue tracker.