Migration Oracle
The Problem
You are rewriting a legacy system. Mainframe to cloud. Monolith to microservices. Microservices back to a modular monolith. One vendor platform to another. The stakes are high and the deadline is real.
The fundamental question of any migration is: does the new system do what the old one did? But the old system's behavior is defined only by its code — code that nobody fully understands, in a language that fewer people read each year, with undocumented behaviors that users have come to depend on.
Migration projects typically rely on test suites written against the old system. But those tests were written by people who understood the old system at the time. They cover the known cases. The unknown cases — the ones that will cause production incidents after migration — remain unknown.
This is why large migrations fail, often silently. The new system passes the tests and diverges in behavior.
The Approach
Before rewriting, write a Spine specification of the old system's behavior. This is closely related to the digital twin scenario, but the intent is different. You are not creating a long-term companion to the production system. You are creating a migration oracle — a reference that will tell you when the new system is done.
The specification captures the rules, not the implementation. It describes what the system does in terms of facts, constraints, and effects. The process of writing it forces the same rigorous examination of behavior as the digital twin — and surfaces the same inconsistencies.
Once the specification compiles and the Spine executable matches the old system's behavior (verified through A/B testing), you have your oracle.
The Outcome
The migration has a definition of done: the new system matches the oracle.
- Objective acceptance criteria — the oracle defines correct behavior. The new system is tested against it, not against human judgment or incomplete test suites.
- Incremental migration — as each module of the new system is built, it can be tested against the corresponding part of the oracle. You know where you stand at every point.
- Behavior documentation — the specification is a precise, verified record of what the old system did. When the migration is complete, it remains as documentation.
The development team builds the new system in whatever stack they choose. The oracle does not constrain their architecture. It only constrains their output.
The Workflow
Legacy System → Specification in Spine → Compile → Migration Oracle → A/B Test Against Legacy
Then, during migration:
New System (in Progress) → A/B Test Against Oracle → Iterate Until Match
The legacy system can be decommissioned once the new system consistently matches the oracle. The oracle itself remains as the verified specification of correct behavior.
Why This Works
Migrations fail because "does the same thing" is undefined. The oracle makes it defined. Not as a list of test cases, but as a verified specification of behavior.
Test suites check scenarios someone thought of. The oracle embodies the complete set of rules. When the new system diverges from the oracle, the specification tells you exactly which rule is violated — not just which test failed, but why.
The oracle is also stack-independent. Whether the new system is Java, Go, Rust, or a cloud-native service mesh, it can be compared against the same reference. The oracle does not care how the system is built, only what it does.