every model spec’d & versioned · harness ✓ greenchangelog →

Writing · Engineering & integration

Backfilling a Legacy Calculator With a Verified Engine

Shadow mode, a diff harness, and a cutover you can defend. The migration pattern for replacing math nobody fully remembers writing.

By Worthune Staff · 2026-08-14

The scariest part of replacing a legacy calculator is not the new engine. It is discovering what the old one actually did — which the migration itself will tell you, if you run it in shadow mode first.

Somewhere in your codebase is a calculator that predates everyone on the current team. It has users, it has history, and it has behavior no document fully describes. Replacing it with a verified model is not a swap; it is an investigation with a deadline. The pattern that works has three phases — shadow, diff, cutover — and the middle one is where the value hides.

Phase one: shadow mode

Keep the legacy calculator serving users. Behind it, mirror every request to the corresponding Worthune model and store both answers side by side, with the response envelope. No user sees the new number yet. Two practical notes: map your legacy fields to the model's contract explicitly in code, with the mapping reviewed against the published spec rather than inferred from field names — decades-old calculators are full of fields whose names stopped being true — and where the model's domain is narrower than what your legacy tool accepted, log the rejections instead of forcing the call. Those rejections are data: they are the population of users your old tool was answering with math outside any studied range.

Phase two: the diff harness

Now compare, and resist the instinct to hope for zero differences. There will be differences, and each one is one of exactly three things.

Diff classWhat it meansWhat to do
Legacy bugThe old tool was wrong — stale constant, edge case, driftQuantify who was affected — fix by cutover, disclose if material
Convention differenceBoth defensible — rounding, timing, day-count conventionsRead the spec's convention — decide if your product copy must change
Mapping errorYour shadow integration mistranslated a fieldFix the mapping and re-run — cheapest of the three

Work the largest diffs first and expect the classes to sort in that order: stale constants are usually the biggest dollars (a contribution limit two tax years old moves answers more than any rounding convention), and the specs' assumptions sections plus the facts registry make classification fast — the spec states its convention, the registry states its constant vintage, so a diff either matches a documented difference or it does not. Keep a written log of every classified diff. That log becomes the migration's compliance artifact: evidence that behavior change at cutover was deliberate, quantified, and explained.

Phase three: cutover

Cut over when the diff log is fully classified and shadow mode has covered a representative traffic window — long enough to include your seasonal shapes: a payoff tool needs paycheck cycles, a tax tool needs nothing older than the current tax-year posture. Ship the cutover with three artifacts: the classified diff log; the fixture-based version pin in CI so the new dependency is drift-monitored from day one; and stored envelopes on every answer from the first post-cutover request. If any user cohort will see materially different numbers — the stale-constant cohort usually will — decide the disclosure deliberately: a note that the tool was updated and figures may differ beats users discovering it.

What the migration leaves behind

The team finishes with more than a replaced calculator. The diff log is the first complete description of what the legacy tool actually did — often the only one ever written. The envelope store means the new tool never becomes the next undocumented legacy: every answer it has ever given is stored with its spec version and provable by hash. And the maintenance calendar that motivated the migration — the constants, the annual updates, the edge cases — is now the platform's, tracked in a public changelog your CI watches. The next team inherits a dependency whose paper trail starts on day one — and nobody has to reverse-engineer the old tool again.

Sources

  1. [1] Worthune API documentation. https://worthune.com/docs
  2. [2] Worthune writing: Version Pinning in CI. https://worthune.com/writing/version-pinning-ci
  3. [3] Worthune writing: Storing the SHA-256 Envelope. https://worthune.com/writing/storing-the-envelope