Skip to main content
Defense Partnerships

Modernizing a legacy defense system with a specialist partner

Modernization programs stall on the systems nobody fully understands. This is the method that moves them: recover the rules from code and historical data, verify each one by execution, build the data layer first, and migrate one reversible slice at a time until the old components can be retired.

Every sustainment portfolio has one: the system that runs the mission, that nobody on the current team wrote, and that no one is willing to touch. The documentation describes a design from two decades ago. The people who knew why a particular branch exists retired. The database has columns whose meaning lives in an operator's head. And the modernization line item has been in the budget for four years, funded, restated, and quietly rolled to the right, because every credible plan starts with "first we understand the current system" and nobody has been able to price that sentence.

This is written for the program director who owns that line item on a sustainment or modernization contract at a prime. The question is not whether the system should be modernized. It is how to get from a system nobody fully understands to a new one that works, without a big-bang cutover, without a year of discovery that produces a document instead of a capability, and without a period where the program has two systems and no way to reconcile them.

Why modernization programs stall in the same place

The stall is almost never technology. It is knowledge. The current system is the only complete statement of what the business rules are, and it states them in a form nobody can read at the speed the schedule requires.

Three specific things go wrong, and they compound.

Discovery produces a document, not a capability. A discovery phase is funded, analysts interview users, and eighteen months later the program holds a requirements package that describes what people say the system does. The gap between what users describe and what the code executes is where every modernization program dies, because the exceptions are the system. The rule everyone can state is the easy ten percent. The four hundred conditional branches accumulated over twenty years of policy changes are the other ninety, and they are only in the code and the data.

The new system is built against the wrong data. Development proceeds against a sanitized extract or synthetic records, and integration meets the real data for the first time in test. Real operational data contains defaults that mean "unknown", codes retired in the nineties that still appear, records that violate the constraints the schema claims to enforce, and free-text fields carrying structured meaning. Each of those is a design input, and discovering them late converts them into rework.

Cutover is planned as an event. A date is chosen, both systems are run in parallel for a period nobody funds properly, differences are found, and the decision to switch becomes a judgment call under pressure with users watching. The programs that succeed do not have a cutover date; they have a sequence of narrow migrations, each of which is small enough to reverse.

What actually reduces schedule risk on a legacy modernization

Running the old and new logic side by side on real production inputs
95%
Building the data layer before any new user-facing feature
91%
Migrating one user population at a time, reversibly
87%
Extracting rules from code and data rather than from interviews alone
82%
Writing an operator-facing decision log for every rule change
75%
A comprehensive as-is requirements document before any build
33%

Editorial weighting, illustrative rather than measured. The last row is deliberately low: the document is a byproduct of the work, not a prerequisite for it.

Extracting the rules: what the work actually looks like

The core technical activity of a modernization is recovering the executable specification from an artifact that was never written to be read. Done well, it produces a rule inventory that both the government and the new implementation can be tested against. Our engineers work it in five passes, and each pass produces something usable rather than a milestone document.

Pass one: the call graph and the dead ends. Parse the source into a graph of programs, procedures, copybooks or modules, and entry points, then walk it from the actual entry points the system exposes. On a system of this age, a large fraction of the code is unreachable — retired paths, abandoned batch jobs, alternate implementations kept "just in case". Establishing what is live shrinks the problem before anyone reads a line, and it is the cheapest step in the whole program.

Pass two: the data flow to the decisions. For each live entry point, trace which fields feed which conditionals. The interesting output is not the code; it is the list of fields that actually change an outcome, and the list of fields that are read, carried and never used. The second list is usually longer, and it tells the data migration team what they do not have to preserve perfectly.

Pass three: rule candidates, drafted by a model and verified by execution. This is where language models earn their place. A model reading a procedure with its copybooks and its variable names produces a plain-English candidate rule far faster than a person can, and it produces it consistently in a schema the team can review. What a model cannot do is be believed. Every candidate rule is a hypothesis, and the pass is worthless without the next one.

Pass four: verification against production behavior. Take the candidate rule, implement it as an executable predicate, and run it against a large sample of real historical transactions alongside the outcome the legacy system actually produced. A rule that reproduces the historical outcome on a hundred thousand records is a rule. A rule that disagrees on two hundred of them has found either a bug in the extraction or a genuine exception nobody documented, and both are valuable. This is the step that converts an AI-assisted reading exercise into evidence.

Pass five: adjudication with the government. The disagreements become a list of questions with real examples attached: here are two hundred cases where the system did something the stated policy does not explain. Every modernization we have engineered found a set of these, and they are the highest-value conversations of the whole program, because the answer decides whether the new system reproduces a behavior or corrects it. Get it in writing either way, and keep the decision log as a deliverable.

A rule that reproduces the historical outcome on a hundred thousand records is a rule. A rule that disagrees on two hundred of them has found either a bug in the extraction or a genuine exception nobody documented, and both are valuable.

Where AI helps on this work, and where it does not

Being precise about this is worth doing in front of a program office, because the honest version is more persuasive than the enthusiastic one.

TaskWhat a model contributesWhat must not be delegated to it
Reading legacy codeFast plain-English candidate summaries in a consistent schema, across far more code than a team can readBelieving the summary. Every rule is verified by execution against historical records
Document intelligenceExtracting structure from scanned manuals, memoranda and change requests that were never digitized as dataTreating an extracted value as authoritative without a confidence threshold and a review queue
Data profilingProposing meanings for cryptic codes by correlating usage patterns across tablesDeciding what a code means. That is adjudicated with the government and written down
Anomaly detectionFlagging records and transactions that differ from the historical pattern during parallel runningDeciding a difference is acceptable. Each one is triaged by an engineer against the rule inventory
Test generationProposing edge cases from the branch structure and the observed data distributionActing as the oracle. The legacy system's historical output is the oracle
Writing the new systemDrafting implementations, migrations and tests under reviewOwning the design. Architecture, data model and interfaces are engineered decisions

The pattern across the table is the same one that governs every use of a model in a system of record: the model proposes, and something deterministic disposes. The value is the speed of proposal across a volume of material no team would otherwise read. The discipline is that nothing reaches the new system on a model's authority.

The data layer comes first

The sequencing decision that most changes the outcome is building the data layer before any new user-facing capability. It feels backwards to a stakeholder who wants to see screens, and it is the difference between a program that delivers and one that demonstrates.

The layer we build has four parts. A change feed off the legacy store, so the new side can be kept current without asking the old system to change: log-based capture where the platform supports it, a timestamp-and-key sweep where it does not, always with a reconciliation job that proves the two sides match rather than assuming it. A canonical model for the entities the mission actually cares about, defined by what the rules need rather than by mirroring the legacy schema, because copying the old schema imports the old constraints and guarantees the new system inherits the problem. A translation layer that maps legacy codes to canonical values, with every mapping carrying the provenance of its decision and every unmapped value landing in a queue rather than defaulting silently. And a write path, planned from the start even if it is used late, because a read-only new system can never take over anything.

Once that layer exists, several things become possible that were not: the new capability can be built and tested against real data from its first sprint; the old and new logic can be run side by side on the same inputs; reporting and analytics can be moved off the legacy system early, which is often the first visible win and the one that buys the program its next increment; and a user population can be moved without a data migration event, because the data is already flowing.

Strangling the old system, one population at a time

The pattern is not new and it is not exotic: put a routing layer in front of the system, move one narrow slice of function behind it to the new implementation, verify, and repeat. What makes it work on a defense sustainment program is the specific discipline applied at each step.

Shadow first, always. Before any traffic is served by the new path, run it in shadow: real inputs go to both implementations, the legacy answer is the one returned, and the difference is recorded. Run it long enough to cover the cycle that matters, which on many systems is a month or a quarter rather than a week, because the end-of-period processing is where the exceptions live. The shadow log is the single best artifact for a program review, and it is what converts "we believe it works" into a number.

Choose the first slice by reversibility, not by value. The temptation is to start with the function that would impress the customer. Start instead with the one where switching back costs an afternoon. The first cutover's purpose is to prove the mechanism: the routing, the monitoring, the rollback, the support path, the user communication. Once that is proven, the valuable slices go faster and with less argument.

Move a user population, not a feature, when the workflow is the unit. Where the mission is organized by site, unit or role rather than by transaction type, the reversible slice is a group of users who do their whole job on the new system while everyone else stays. That surfaces the workflow problems a feature-by-feature migration hides until the end.

Keep the difference report running after the switch. When the new path becomes authoritative, do not turn off the comparison. Let the legacy path keep computing in shadow for a stated period. It costs almost nothing and it is the only way to detect that a rare quarterly path was never exercised during the trial.

Write down the retirement criteria. A legacy system that is never decommissioned means the program pays for two systems permanently, which is how modernization savings evaporate. State, at the start, what conditions permit shutting off each legacy component, then treat those conditions as requirements.

How a first increment should be judged

A slice in production for real users, reversible in an afternoon
94%
A shadow-comparison report with a measured agreement rate
89%
A verified rule inventory covering the migrated function
85%
A data layer the next increment builds on without rework
80%
Adjudicated answers on the exceptions the extraction found
76%
A demonstration environment shown at a review
30%

Editorial weighting, illustrative rather than measured. The last row is deliberately low: a demo proves the team can build, not that the system can be replaced.

The security and accreditation path is part of the design

A modernization that stands up new infrastructure inherits an accreditation problem, and the programs that handle it well decide the destination in the first weeks rather than the last. Three questions settle most of it. Does the new capability live inside the existing authorization boundary, extend it, or need its own? Which controls are inherited from the hosting environment and which the program must implement and evidence itself? And what does the change process look like once the system is authorized, because a modernization that can only deploy at an annual review has traded one rigid system for another.

The engineering consequence is that control evidence is generated by the pipeline rather than assembled by hand at the end. Access control, audit logging, encryption in transit and at rest, configuration baselines, vulnerability scanning and dependency provenance are all things a build system can produce continuously as artifacts. The same is true of accessibility: Section 508 conformance is cheap when the component library is built to it and tested in the pipeline, and expensive when it is a remediation project against a finished interface. Both belong in the definition of done for every increment, not in a phase.

How we work inside a prime's program

Precision Federal builds AI, data platforms, software, cloud and full-stack systems and delivers them into production inside federal agencies. On a modernization or sustainment program we come in as the specialist subcontractor on the extraction, data layer and new-build scope while the prime holds the contract, the customer relationship, the operations and the overall systems engineering.

The first four weeks. We take a source snapshot and a production data extract under whatever handling rules apply, run the reachability and data-flow passes, profile the data, and produce three things: a live-code map with the dead paths identified, a first rule inventory for the highest-value function with its verification results against historical records, and a written increment plan naming the first reversible slice with its acceptance criteria. That is a working artifact, not a study, and it is enough for the program to decide whether to proceed with evidence rather than optimism.

Weeks five through sixteen. The data layer, the shadow comparison, and the first slice in production behind the routing layer. Everything is built in the prime's environment, in the prime's repositories, under the prime's pipeline and the program's security controls. We write to the program's CDRL formats and standards, not ours.

What the prime keeps. All of it. Source code, the extraction tooling, the rule inventory and its verification results, the data pipelines, the infrastructure definitions, the documentation, and the customer relationship. We assign the intellectual property in the delivered work by a present written assignment, name and carve out any pre-existing tooling we bring and license it back perpetually so the sustainment team is never blocked, and deliver an exit package as a condition of final payment: repository, build pipeline, infrastructure as code, environment configuration, credential rotation and a runbook, with a handover rehearsal where the receiving team deploys while our engineers watch. We are named on the bid or not as the prime prefers; on a scored proposal, a named specialist with a defined technical scope and committed key personnel usually reads better to an evaluator than an unnamed pool.

How it is priced. The extraction and increment plan works well as a firm-fixed-price first milestone with written acceptance criteria, because its output is defined. The build increments work as either fixed-price milestones with measured acceptance or a committed team at a fixed monthly rate across a task order period, which suits option years where the sequence is set by adjudication outcomes nobody can schedule in advance. We are comfortable starting small so a new teaming relationship proves itself before either side commits to a large workshare.

Five ways this goes wrong

The program buys a study. A discovery contract whose deliverable is a document produces a document. Make the first deliverable a verified rule inventory and a working data path, and the understanding comes with it.

The new schema copies the old one. Mirroring the legacy data model is the fastest way to migrate and the surest way to inherit every constraint that made the old system hard to change.

Nobody adjudicates the exceptions. The two hundred cases where behavior and policy disagree sit in a spreadsheet while development guesses. Every guess becomes a defect found by a user.

Parallel running is scheduled but not staffed. Shadow comparison generates differences, and differences need engineers to triage. Fund that work or the report is ignored and the switch becomes a judgment call again.

The old system is never turned off. Without written retirement criteria treated as requirements, the program ends with two systems, two sustainment lines and no savings to show.

Bottom line

A legacy modernization is a knowledge recovery problem wearing a software project's clothes. The rules that matter are in the code and the historical data, not in the interviews, and they are recovered by reading at machine speed and verifying by execution against real production outcomes. Build the data layer first, run the old and new logic side by side on real inputs, migrate one reversible slice at a time, and adjudicate every disagreement in writing with the government. Programs that do this deliver capability in months and retire components on a schedule. Programs that start with a comprehensive as-is document deliver the document. The first step is one email with a one-page brief describing the system, its platform, the data and the increment you want first, and we return a scoped, priced statement of work.

Frequently asked questions

How do you modernize a system nobody understands anymore?

Recover the rules from the two artifacts that cannot be wrong: the source code and the historical transaction data. Map what code is actually reachable, trace which fields change outcomes, draft candidate rules from the code, then verify each one by running it as an executable predicate against a large sample of real historical records and comparing with what the legacy system actually did. Rules that reproduce history are confirmed. Disagreements become adjudication questions with concrete examples attached.

Can AI read legacy code and produce the business rules?

It can draft them, quickly and consistently, across far more code than a team could read. It cannot be believed on its own. Treat every model-produced rule as a hypothesis and verify it by execution against historical outcomes. That pairing is what makes the approach defensible in front of a program office: the speed comes from the model, the evidence comes from the data. Nothing reaches the new system on a model's authority.

What is the alternative to a big-bang cutover?

Put a routing layer in front of the legacy system and move narrow slices behind it one at a time. Run each slice in shadow first, with real inputs going to both implementations while the legacy answer is still the one returned, long enough to cover the end-of-period processing where exceptions live. Choose the first slice for reversibility rather than visibility, so the initial migration proves the routing, monitoring, rollback and support path cheaply.

Why build the data layer before new features?

Because everything else depends on it. A change feed off the legacy store plus a canonical model and a translation layer makes it possible to build against real data from the first sprint, run old and new logic side by side, move reporting off the legacy system early as a visible win, and migrate users without a separate migration event. Building features first means integrating with real data late, which is where modernization schedules are lost.

How should a modernization increment be priced?

Split it. The extraction and increment planning has a defined output, so it works as a firm-fixed-price milestone with written acceptance criteria. The build increments work either as fixed-price milestones with measured acceptance criteria on named datasets, or as a committed team at a fixed monthly rate where the sequence depends on adjudication outcomes that cannot be scheduled. Starting with a small fixed-price first milestone lets a new teaming relationship prove itself before a large workshare is committed.

1 business day response

Have a modernization line item that keeps rolling right?

We extract and verify the rules, build the data layer, and deliver the first reversible slice into production in your environment. Send a one-page brief and we return a scoped, priced statement of work.

How we workMore insights →Email an engineer or email bo@precisionfederal.com
UEI Y2JVCZXT9HP5CAGE 1AYQ0NAICS 541512SAM.GOV ACTIVE