Rewrite vs convert vs wrap: choosing a legacy migration strategy honestly

Every legacy application owner eventually sits through three contradictory sales pitches:

  1. “Rewrite it” — from a dev shop that has never seen your business rules.
  2. “Convert it automatically” — from a tool vendor whose demo compiles your code to C# in an afternoon.
  3. “Don’t touch it, just wrap it” — from whoever will be blamed if the migration fails.

All three strategies are real, and each is correct somewhere. Here is the honest comparison — including the option the pitches skip.

Rewrite: rebuild behavior on a new stack

A rewrite does not have to mean “start from the requirements and hope”. Done properly, the old system itself is the specification: you capture its actual behavior as an executable parity harness — reports, totals, edge cases, bugs included — and rebuild module by module until the diff is empty.

  • Get: a system you fully own — modern stack, hireable developers, testable code, and the first real documentation the application has ever had (the harness itself).
  • Pay: the most money and calendar time of the three. The parity harness is 15–25% of the budget before any new code runs — that is the price of “nothing changed except the platform”.
  • Fail mode: the unharnessed rewrite — screens rebuilt from screenshots, rules from memory. This is the version that produced the migration horror story your CFO remembers, and it deserves its reputation.

Convert: transpile the code automatically

Conversion tools parse your Clipper/FoxPro/VB/PowerBuilder code and emit the equivalent in a modern language. The demo is genuinely impressive: a week in, everything compiles.

  • Get: speed to “runs on the new platform”, preserved logic (including logic nobody understands), and sometimes the only viable path when the codebase is enormous and the budget is not.
  • Pay: afterwards. The output is your old program wearing a new language — xBase idioms, global state and GOTO-shaped control flow transliterated into C# that no C# developer will enjoy or safely change. You have swapped a maintenance problem you knew for one you do not.
  • Fail mode: treating conversion as the destination. As a bridge — convert to retire the dead platform today, then refactor with the converted code as a reference — it can be rational. As an endpoint, it usually means paying for the same migration twice.

Wrap: keep the engine, replace the surface

Wrapping keeps the legacy core running and builds new access around it: a web front-end over the old database, an API layer screen-scraping or driving the old app, new reports reading a mirrored copy of the data.

  • Get: fast, cheap, low-risk wins — modern UI for the 20% of workflows that needed it, integration endpoints, reporting freedom. Often the right first move, and sometimes right for years.
  • Pay: the legacy core is still there — same platform risk, same 2 GB limits, same single point of failure, plus a new synchronization layer to operate. Complexity went up, not down.
  • Fail mode: the permanent temporary solution. The wrap relieves the pain that was funding the migration, the project stops, and five years later the organization runs two systems forever. Wrap with an explicit expiry date or do not wrap.

The skipped option: contain, then decide

For 16-bit-era xBase systems there is a fourth move the pitches rarely mention because no one sells licenses for it: containment on an open-source runtime. Recompiling Clipper-dialect code with Harbour produces a native modern executable on the same data files — the platform emergency (dying hardware, DOS boxes, 16-bit Windows) ends in weeks, for a fraction of any other option, without betting the business on a big project.

Containment is not the destination either. It is what buys the calm in which a rewrite can be done properly instead of heroically.

How to actually choose

QuestionIf the answer is yes →
Is the platform actively collapsing (hardware, OS, drivers)?Contain first — remove the emergency before deciding anything
Will the business still run on this logic in 10 years?Rewrite, parity-tested, in slices
Is the codebase huge, the budget small, and the platform dead?Convert — as a bridge with a refactoring plan, not an endpoint
Is the pain concentrated in access (UI/integration/reporting), not the core?Wrap — with a written expiry date
Is the application mostly habit?Retire it — the cheapest migration is an export and an archive

Two patterns from the field, offered as priors: the total cost ranking over a 10-year horizon is usually retire < contain < rewrite < wrap-forever < convert-then-rewrite-anyway. And the single best predictor of migration success is not the strategy chosen — it is whether the current system’s behavior was captured as tests before anyone wrote new code.

Our assessment prices all applicable paths for your specific system — including the ones we would not be hired for. That is deliberate: a roadmap you can sanity-check against a vendor’s pitch is worth more than any pitch.

Written from real project experience; details anonymized. Questions about your own system? Get in touch — first look is free.

Start with a fixed-price Legacy Assessment

One to two weeks. You get a full inventory of the application and its data, a risk map (what breaks first, what is undocumented, what nobody can rebuild), a data-quality report and a migration roadmap with honest effort estimates — a document you can execute with us or with any other team. Fixed price, agreed before we start.

Book an assessment Undecided? Rewrite vs convert vs wrap