A financial calculation engine is being replaced and the results must be proven equivalent before cutover. How should a parallel run be designed, and how are discrepancies triaged?
Show the full answer Hide the answer
Why a parallel run rather than testing
Test suites verify the cases someone imagined. A financial engine's risk is concentrated in the cases nobody imagined — historical records with unusual shapes, edge cases in rounding, accumulated data from previous system versions, and behaviours introduced years ago for reasons now forgotten.
A parallel run tests against reality, which is the only source of inputs that contains those cases.
The design
- Both systems process the same real inputs, with the legacy result authoritative and used, and the new result recorded for comparison. Users are unaffected throughout.
- Run for a full business cycle at minimum — month-end, quarter-end, and any annual process. The rare periodic calculation is where the differences concentrate, and a two-week parallel run systematically misses it.
- Compare at multiple levels: the final figure, the intermediate components, and the inputs each system actually consumed. A matching total with differing components is a coincidence waiting to stop being one.
- Define tolerance explicitly and by field. Floating-point differences in the last decimal place may be acceptable in an intermediate value and are not acceptable in a posted amount. A single global tolerance is always wrong in one direction or the other.
- Automate comparison and triage, because at volume the differences must be classified by machine before a human can look at them.
Triaging discrepancies
Every difference falls into one of four categories, and assuming the first is the failure mode:
- The new system is wrong. The expected case; fix and re-run.
- The legacy system is wrong. It happens more often than teams expect, and it is the most difficult situation — because correcting it changes historical figures, which may have been reported, audited or used in decisions. The resolution is a business and possibly regulatory conversation, not a technical one.
- Both are defensible and the specification was ambiguous. This is where the real requirement is discovered, and the outcome should be a documented decision rather than a code change alone.
- The inputs differed, which is not a calculation difference at all and is frequently the largest category early on — different data feeds, timing, or filtering.
Rule: no discrepancy is closed without a category and an explanation. "Rounding" as an unexamined explanation is how a genuine defect is closed as noise, and it is the most common way a parallel run produces false confidence.
The exit criteria, agreed in advance
Written before the run starts, because they cannot be negotiated honestly afterwards under schedule pressure:
- Zero unexplained differences in the authoritative outputs, for a defined number of consecutive cycles.
- All differences categorised, with those in category 2 having a documented business decision.
- Performance and operational readiness demonstrated at production volume.
- A defined rollback available for a period after cutover.
The cutover and after
Switch authority, and keep the legacy system running and calculating in parallel for a further period. The first live period is when the remaining differences surface, and having the legacy result available makes an unexpected discrepancy diagnosable rather than alarming.
Then decommission with a date, in the same funded project. A parallel run that never ends is the most expensive possible outcome — two systems, two teams, two sets of changes forever — and it is a genuinely common one, because nobody wants to be the person who turned off the safety net.