Skip to main content
Back to Blog

Anatomy of a Validated Migration

Steve HarlowAugust 2, 20269 min read

"It converted" is not a claim worth much on its own. A query can convert, run without error, and still return the wrong answer, which is the failure mode that actually hurts a migration. Here is what "converted" means in our pipeline, stage by stage, and where each stage stops short of proving something it does not prove. If you have not yet run the construct scan that decides which of your queries reach this pipeline cleanly, see the 10 conversion gotchas first.

Stage 1: Static Assessment, Before Anything Runs

Before a query is converted at all, the free assessment classifies it from the .rdl file alone, which T-SQL constructs it contains, auto-convertible or known-hard. This stage is honest about its own ceiling: it is a static scan, not a guarantee and not a quote. It cannot see your data volume, schema drift, collation behaviour, or what is hidden inside a stored procedure. That is exactly why the estimate it produces is a range, capped well below 100%, rather than a single confident number.

Stage 2: Automated Conversion, Up to Three Fix Rounds

The AI conversion pass rewrites the T-SQL for PostgreSQL syntax using your live schema as context. When the first attempt fails, the pipeline does not stop there: the converted SQL is tested via EXPLAIN against your live PostgreSQL database, the error is fed back to the AI for correction, and this loop runs up to three times per query before a dataset is either accepted or flagged for a human.

Stage 3: EXPLAIN Plus a LIMIT 1 Execution

A dataset counts as converted when its generated PostgreSQL passes an EXPLAIN plan check plus an actual LIMIT 1 execution against a live database. This is a real run, not a syntax check, it proves the query plans and executes. It does not prove the results match SQL Server. Those are two different claims, and conflating them is exactly the kind of mistake that lets a silently wrong report ship.

Stage 4: The Parity Check

Once a query executes cleanly, it still has to agree with the original. The parity check runs the report against both SQL Server and PostgreSQL and compares total row counts for exact equality, plus a cell-by-cell diff of a sample of rows. You see exactly which reports match and which need manual attention before cutover, not a guess based on the fact that the query ran without an error.

Stage 5: Frozen, Verified, Locked

Once a conversion passes and is verified, it is frozen: the converted SQL is hash-locked so a later pipeline change or model update cannot silently alter a query that already works. This is what turns validation into something durable rather than a one-time check. A report that passed six months ago is still running the exact SQL that passed, not a fresh reconversion that happens to look similar.

What 95.8% Actually Measures

"Effective conversion rate" counts report datasets, the individual SQL queries inside an RDL, of which one report can have several, not whole reports. A dataset counts as converted when its generated PostgreSQL passes the EXPLAIN plan check and the LIMIT 1 execution described in Stage 3, after the automated fix rounds in Stage 2. Ours is 317 of 331 scorable datasets across a 190-report production library. It measures whether the query runs, not that its results match SQL Server row for row, that is Stage 4, a separate step. It is our historical rate on our own library, not a prediction for your estate.

What Even This Does Not Prove

Five stages of validation is not the same as zero risk, and pretending otherwise would be exactly the overclaim this whole pipeline exists to avoid. The Stage 1 estimate is static and cannot see your data volume or schema drift. The Stage 4 parity check samples rows rather than comparing every one. And none of it validates business logic that lives outside the query itself, a downstream calculation, a display rule, a report that is "correct" only because someone with domain knowledge says so. Validation narrows where the risk can hide. It does not remove the need to look.

Steve Harlow is the founder of ReportBridge. He built this validation pipeline while converting nearly 200 production report queries for a multi-jurisdictional regulatory program. Questions? steve@report-bridge.com

Frequently Asked Questions

Does passing EXPLAIN and LIMIT 1 mean the report's results match SQL Server?

No, and this is the distinction the whole pipeline is built around. EXPLAIN plus a LIMIT 1 execution proves the converted query runs against a live PostgreSQL database, that it is syntactically and semantically valid. It says nothing about whether the results match SQL Server row for row. That is a separate step, the parity check, and it happens after a query passes execution validation, not instead of it.

What does the parity check actually compare?

Total row counts, checked for exact equality, plus a cell-by-cell diff of a sample of rows, up to 20. It is a strong signal, not an exhaustive guarantee, a difference outside the sampled rows would not be caught by the diff alone, which is why row-count equality is checked independently rather than relied on to imply the sample is representative.

Why lock a conversion once it passes?

Because a pipeline that keeps improving is also a pipeline that can regress a query that already works. Once a dataset's converted SQL passes validation and is verified, it is frozen and hash-locked: a later model change or pipeline update cannot silently rewrite it. Anyone reviewing a frozen conversion later is reviewing the exact SQL that was verified, not a fresh guess.

Does static analysis before conversion have the same guarantees?

No, and this is worth being direct about. The free scan that estimates your auto-conversion band before you commit to anything is a static read of your .rdl files. It cannot see your data volume, schema drift, collation behaviour, or what is hidden inside a stored procedure. The validated pipeline described here runs after that estimate, against a live database with real generated SQL, which is a different and stronger kind of check, but even it stops at execution and parity, not a guarantee that every business rule downstream of the query behaves identically.

See the Pipeline Run Against Your Own Reports

Cohort 1 is enrolling. Apply and we will tell you honestly what this validation pipeline finds in your estate, including what it flags for a human.