The 5-year modernization that could have been 18 months: sequencing sins

Blown modernization timelines rarely come from one disaster. They come from a plan that serializes work that could have run in parallel, and treats an open-ended exit condition as a fixed-length phase.

Ask a program office how long the modernization is supposed to take and you'll get a number from the plan: eighteen months, two years, something board-presentable. Ask how long it actually took, on the ones that finished at all, and the honest answer is usually a multiple of that — three years, five years, sometimes longer, with the original schedule quietly retired somewhere around year two and never spoken of again. The gap doesn't come from one catastrophic failure. It comes from a handful of ordinary sequencing decisions, made early and rarely revisited, that turn a linear plan into a project that can only ever run in series when most of it could have run in parallel.

The dependency chain nobody drew

Every modernization plan has an implicit graph: which pieces of work can start only after which other pieces finish. Most program plans never draw that graph explicitly. They draw a timeline instead — a sequence of phases with tidy boundaries — and the timeline quietly assumes the dependency chain is longer than it actually is, because a chain is easier to schedule and easier to staff one team against than a graph is. Discovery finishes, then design starts. Design finishes, then build starts. Build finishes, then test starts. Each handoff looks disciplined on a slide. In practice, most of what "design" needs to know about a subsystem was knowable the moment its legacy code was read, which is to say during discovery, and most of what "test" needs — real inputs, a working comparison harness, negative controls — could have been built while "build" was still underway rather than queued to start after it. A plan that serializes everything that could have been parallelized isn't being careful. It's manufacturing schedule length and calling it rigor.

Sequencing sin #1: one team, many subsystems, in a line

The most common version of this mistake is staffing the whole program as a single stream that walks the subsystem list top to bottom. It looks efficient — one team, one methodology, no coordination overhead between parallel workstreams. It is efficient, for the vendor's headcount. It is the opposite of efficient for the calendar, because subsystem forty doesn't start until subsystem one through thirty-nine have each been carried through the full pipeline by the same limited group of people. Most legacy systems decompose into modules with real seams — batch jobs that don't share state with online transaction processing, reporting that reads but never writes, subsystems that only a handful of other subsystems call into. Those seams are exactly where independent teams can work in parallel without stepping on each other, and exactly where sequencing plans routinely fail to look, because drawing the seams honestly requires understanding the system before the contract is signed, and understanding it deeply enough to decompose it correctly is unpaid work that doesn't show up as a deliverable.

Sequencing sin #2: testing infrastructure built last

A comparison harness, a production-data extraction pipeline, negative controls that prove the harness can actually detect a discrepancy — none of that is glamorous, and none of it produces a demo. So it gets built last, often only once a first batch of converted code is ready to test against something. This is backwards. The harness is infrastructure the entire program depends on; every subsequent subsystem's testing timeline is gated on it existing and being trustworthy. Build it first, against the legacy system alone — no converted code required, since a comparison harness only needs two things to run against each other and the legacy system paired with itself is a perfectly good first target for proving the plumbing works — and every team that comes after inherits working test infrastructure instead of waiting for someone to build it under pressure mid-program, usually right when the first parity gaps show up and everyone least has time to build a testing tool carefully.

Sequencing sin #3: parallel run treated as a phase instead of a gate

Parallel run gets scheduled as a block near the end — a fixed number of months where old and new systems run side by side before cutover. That framing hides the actual dependency: parallel run isn't a phase with a duration, it's a gate with a pass condition, and the pass condition is "matching output on production-representative inputs for long enough to cover the business's real variance." If that condition is defined loosely, or not defined at all before the clock starts, the parallel run doesn't end on schedule — it becomes the treadmill this blog has described before, running indefinitely because nobody agreed in advance what "done" looks like. Scheduling a fixed-duration block for an unbounded exit condition isn't a sequencing choice, it's wishful arithmetic, and it's one of the most reliable ways a program that looked eighteen months away from done on the plan turns out to be two years away from done in reality.

What compresses the timeline without cutting corners

None of this argues for less rigor — quite the opposite. Compressing five years into eighteen months honestly requires more upfront discipline, not less: a real dependency graph instead of an assumed one, subsystem decomposition done early enough to staff multiple teams against genuine seams, test infrastructure built and validated before the first line of converted code exists, and a parallel-run exit condition written down and agreed before parallel run starts, not negotiated once everyone's tired of running it. The programs that actually hit something close to their original schedule aren't the ones that skipped steps. They're the ones that figured out, early and honestly, which steps genuinely had to happen in order and which ones only looked that way because nobody had bothered to check.

Proof beats promises

Torsova modernizes mainframes the only way that should be legal: deterministic translation (no AI in the conversion path), byte-for-byte parity against your real data, and a reproducible demo you can run before you sign anything.

Ask for the proof demo