How We Structure a Legacy System Audit Before Any Migration Work Starts
Every legacy modernization engagement we take on at 137Foundry starts with the same phase, before a single line of replacement code gets written: a structured audit of what the existing system actually does. Here's the process we've settled on after running this enough times to know which shortcuts are safe and which ones aren't.
Step 1: Map the system's actual footprint
Before anything else, we catalogue every input the system receives and every output it produces, including the quiet, undocumented ones. Legacy systems accumulate dependents nobody remembers: a nightly export a different team scripted against years ago, a manual report someone pulls quarterly. We've been burned before by assuming a system's "known" integrations were the only ones, so this step now gets a deliberate, checklist-driven pass rather than relying on whoever's currently around to remember them all.
Step 2: Interview everyone who touches the system, ranked by exposure
We start with whoever fields the most support tickets related to the system, since they've built the most current, continuously updated mental model of where it misbehaves. From there we work outward to finance or operations staff who consume its output, and finally to engineers who've patched it recently. Each layer surfaces a different kind of knowledge, and we've found that starting with support staff rather than engineers usually surfaces the most business-relevant edge cases fastest.
Photo by www.kaboompics.com on Pexels
Step 3: Read the code specifically for business logic, not architecture
A standard code review asks "is this well structured." Our audit read asks a different question: "what business decision does this specific conditional encode, and does anyone currently at the company know why." We flag anything that looks like a business rule rather than a technical necessity for follow-up in the interview phase, since code alone rarely explains its own motivation.
Step 4: Build a prioritized decision record, not an exhaustive one
Not every quirk deserves the same depth of investigation. We rank findings by how often they fire and how expensive a wrong answer would be, and we're explicit with clients that some low-frequency, low-stakes edge cases will get a lighter touch. Trying to fully resolve every single discovered oddity turns a two-week audit into a two-month one, and the marginal edge cases usually aren't where the real risk lives anyway.
Step 5: Confirm what's safe to drop, not just what to carry forward
A meaningful fraction of what an audit surfaces turns out to be dead logic: a rule that applied to a regulation, a promotion, or a business condition that no longer exists. We treat "we're deliberately not carrying this forward" as a valid, documented outcome, distinct from and much safer than silently dropping something during a code cleanup without ever confirming it was actually safe to lose.
How long this actually takes
Clients often ask for a time estimate up front, and the honest answer scales with how central the system is to daily operations, not with its raw line count. A system that touches a handful of internal reports might take a few days to audit thoroughly. A system that's core to billing, fulfillment, or regulatory compliance can reasonably take several weeks, since the interview phase alone requires scheduling time with people who have their own full workloads. We'd rather give a wider estimate up front than compress the audit later to hit an optimistic one.
What this buys the client
Clients sometimes push back on the time this phase takes, understandably, since it doesn't produce visible progress on the replacement system itself. What it buys is a specification for the new system that's actually complete, rather than one reconstructed purely from reading old code without the business context behind it. The alternative, skipping straight to the rewrite, tends to produce a technically clean replacement that quietly gets specific edge cases wrong for months after launch, which costs far more in incident response than the audit would have cost up front.
We've written up the fuller framework, including how the audit feeds into a parallel-run verification period before any legacy system actually gets decommissioned, in our guide on sunsetting a legacy system without losing institutional knowledge.
Wikipedia's entry on legacy systems covers general background on why these systems accumulate undocumented complexity.
Wikipedia's entry on knowledge management covers the broader discipline our audit process is a practical, narrow application of.
ISO's website maintains formal standards around organizational knowledge management for teams that want a more structured framework than an ad hoc process.
This audit phase is the least glamorous part of any legacy modernization project we run. It's also, consistently, the phase that determines whether the rest of the project goes smoothly or turns into a year of chasing down confusing edge-case bugs after the fact.
A habit we've picked up from doing this repeatedly
After running this process across enough different clients and systems, one pattern holds consistently: the clients who push back hardest on the audit timeline at the start are almost always the ones who end up most grateful for it once it surfaces something they genuinely didn't know about their own system. We've stopped treating that initial pushback as something to argue away up front and started treating it as something the audit itself resolves, once there's a concrete finding on the table instead of an abstract argument about process.
If you're on the client side of one of these engagements and feel skeptical about the time an audit is asking for, that skepticism is reasonable and worth voicing directly rather than quietly working around. The conversation that actually resolves it isn't us insisting the process is necessary in the abstract. It's agreeing on a small, time-boxed first pass and letting whatever it surfaces make the case for the rest.
We've come around to running that first pass as a fixed, capped engagement, a week, not open-ended, specifically so a skeptical client isn't being asked to commit to an unbounded process on faith. Once that first week produces something concrete, the conversation about the remaining scope gets a lot easier on both sides.
What we tell clients who want to skip straight to the rewrite
Every so often a client comes to us wanting to skip the audit entirely and go straight to building the replacement, usually because they're confident their team already understands the old system well. We don't argue against that confidence directly. Instead we ask for a short list of the system's known quirks as they currently understand them, then spend a day or two of lightweight code and log review checking that list against what the system actually does. More often than not, that quick pass turns up at least one thing the team didn't know about, which tends to settle the question of whether the fuller audit is worth doing far more effectively than us simply insisting on it. It's a cheap way to let the evidence make the argument instead of us, and it costs the client almost nothing to find out either way.