Skip to content
Of Ash and Fire Logo

Legacy System Integration and Reverse Engineering

Legacy system integration explained: where to connect, a four-step method for undocumented APIs, zero-downtime data extraction, legal limits and cost ranges.

TL;DR

Key Takeaways

  • Legacy system integration connects older software a business depends on to newer applications through one of six surfaces: the database, files and exports, network or API traffic, a vendor API or SDK, message queues and interface feeds, or the user interface.
  • A repeatable way to reverse engineer an undocumented interface is to enumerate everything it exposes, probe each operation with small tests, validate every response against a strict schema, and put an owned abstraction layer on top.
  • Thoughtworks moved using GenAI to understand legacy codebases to Adopt in November 2025, but noticing when a vendor update changes the data still depends on strict schema validation and contract tests.
  • To extract data without downtime, start change capture before copying history, load the history from a backup or replica, replay the overlap, handle deletes explicitly, and run the new feed in parallel before cutting over.
  • Reverse engineering for interoperability is often lawful in the US, but courts have enforced license clauses that forbid it, so review the license and MSA with counsel first.
·21 min read
legacy integrationreverse engineeringmanufacturingeducationoil and gashealthcarevendor lock-inai

Written by Daniel Ashcraft — 12+ years building HIPAA-compliant software for healthcare organizations, including EHR integrations (Epic, Cerner), telemedicine platforms, and clinical decision support systems.

This article is informed by hands-on healthcare software development experience. For legal compliance decisions, consult qualified healthcare compliance counsel.

Legacy system integration is connecting older software your business depends on, such as an on-premise ERP, a student information system or an older EHR, to newer applications so data moves between them. When the vendor offers no usable API, you reverse engineer the interface from the database, files, network traffic or screens and wrap it in an API you own.

What is legacy system integration, and how is it different from modernization?

Integration leaves the old system running and connects to it. Modernization changes or replaces the old system. Integration usually comes first, because a working connection buys time to decide what to replace.

A legacy system here is any system the business depends on that is hard to connect to: no API, an API that covers a fraction of the data or only the vendor's cloud customers, or nobody left who understands it. Age matters less than access: a locked-down 2019 SaaS product can be harder to integrate than a 1990s AS400 application with a clean Db2 schema.

Reverse engineering here means working out how a system stores and exchanges data by observing it: its schema, its files, its client-server traffic and, less often, decompiled code. The output is an interface specification, and none of the vendor's code ends up in yours.

Vendor lock-in is why this lands on an operations or finance leader's desk. If your data can only leave through the vendor's export button, every integration and migration happens on the vendor's schedule and at its price. With an integration layer you own, the next system you buy or build talks to your layer instead.

Where can you connect to a legacy system?

There are six places to attach: the database, files and exports, network or API traffic, a vendor API or SDK, message queues and interface feeds, and the user interface. Pick the lowest-risk surface that carries the data you need, and expect to use more than one.

Our student data pipeline for 12 districts in three states used five routes for five SIS sources: a REST API for PowerSchool, SOAP web services for Infinite Campus, XML feeds for Skyward, direct SQL Server access for Aeries, and flat-file exports over SFTP for one district's legacy system.

SurfaceTypical examplesWhat you getMain risksProduction impact
DatabaseSQL Server under an on-prem ERP, Db2 for i on IBM i, Oracle under a hospital systemEverything the application stores, at full fidelityUndocumented schema, business logic that lives in application code, support terms that forbid direct access, writes that skip validationLow for reads from a replica or snapshot; never write directly
Files and exportsCSV and fixed-width exports, SFTP drops, report dumps, SEG-Y and other binary formatsWhatever the export includes, on a scheduleFormat changes without notice, partial exports, encoding quirks such as EBCDICVery low
Network or API trafficSOAP calls between a thick client and its server, an undocumented REST API behind a web appThe same calls the vendor's own client makes, including writesUndocumented behavior, session handling, encryption you may not be allowed to breakLow if you replay only reads at first
Vendor API or SDKREST v2 on Epicor Kinetic, Blackbaud SKY API, a FHIR endpoint, an OpenAPI specSupported, documented operationsCoverage gaps, rate limits, availability tied to a hosting tier or a paid moduleLow; this is the supported path
Message queues and interface feedsHL7 v2 feeds, IBM i data queues, OPC UA, MQTT, EDIMessages in real time or in batches, depending on the protocolInterface license fees, message variants, delivery guarantees you have to build yourselfLow once the feed exists
User interface automation5250 green screens, desktop forms, web pages with no APIAnything a user can see or typeBreaks when a screen changes, slow, hard to make transactionalModerate; uses real sessions and licenses

Two rules decide most choices. Read from the lowest surface that has the data, meaning the one closest to storage, because databases and files change less often than screens. Write through the highest supported surface, closest to the application's logic, because much of that logic (pricing rules, inventory reservations, audit trails) lives in application code that direct table writes bypass.

How do you reverse engineer an undocumented API or system?

We use four steps: enumerate everything the system exposes, probe each part with small tests, validate every response against a strict schema, and put an abstraction layer you own on top. The method comes from a project where two earlier teams had given up, and we have reused it on two more since.

That project, described in our legacy API reverse engineering case study, was an ISP's CRM with an undocumented SOAP/WSDL API: more than 12 services, hundreds of operations and more than 49 polymorphic context types. Generalized, the steps look like this:

  1. Enumerate. Build a complete inventory before writing integration code. For a SOAP API that meant parsing every WSDL into a catalog of services, operations and types. For a database it means the schema, row counts, foreign keys, triggers and stored procedures; for a binary file, samples from every version you can find.
  2. Probe. Treat integration tests as probes that discover behavior. Call each operation with the smallest valid request, read the response or fault, adjust, and record what the system actually does. A passing probe becomes a regression guard. Start with reads. Without a test environment, which is common on-premise, probe writes with labelled synthetic records in a quiet window and clean them up. Catalog every error code.
  3. Validate. Define a strict runtime schema for every response and fail loudly on anything unexpected. In the CRM project we modeled the 49+ polymorphic types as discriminated unions in Zod and versioned the schemas so new variants could be added deliberately. The case study reports those schemas caught three vendor-side changes that would otherwise have become silent data errors in production.
  4. Abstract. Put a typed client or service of your own in front of the legacy system. It handles sessions, retries and error mapping (in that project, SOAP faults became HTTP 401, 404 and 422), so the rest of your software never sees the vendor's quirks. Retry reads and idempotent operations automatically; for a create, check whether the record already exists before retrying, or a lost response becomes a duplicate order. When the vendor changes or the system is replaced, this layer is the only integration code that changes.

Here is validation in TypeScript with Zod, simplified from our pattern for polymorphic responses:

import { z } from "zod";

declare function reportSchemaDrift(
  schema: string,
  recordId: string | undefined,
  issues: z.ZodIssue[],
): void; // your alerting and quarantine queue; log ids and issues, not payloads

const ServiceAddress = z.object({
  kind: z.literal("service_address"),
  id: z.string(),
  line1: z.string(),
  postalCode: z.string(),
}).strict();

const BillingAccount = z.object({
  kind: z.literal("billing_account"),
  id: z.string(),
  balanceCents: z.number().int(),
}).strict();

export const Context = z.discriminatedUnion("kind", [ServiceAddress, BillingAccount]);

export function parseContext(raw: unknown) {
  const result = Context.safeParse(raw);
  if (!result.success) {
    // Unknown variant or changed field: quarantine the record, do not guess.
    const id = (raw as { id?: string } | null)?.id;
    reportSchemaDrift("Context", id, result.error.issues);
    return null; // callers must handle a quarantined record explicitly
  }
  return result.data;
}

The .strict() call rejects fields the schema does not know about, so you find out the vendor added something before a downstream report quietly drops it. How hard to fail is a policy choice. A reasonable default is to quarantine records with an unknown variant or a missing required field, and to alert, without quarantining, on extra fields you don't consume, so a harmless vendor addition doesn't stop the feed.

The steps apply outside APIs too. On a database, probing means diffing tables while a user performs a known transaction. On a file format, it means changing one export setting and comparing bytes. On network traffic, it means recording sessions with a proxy such as mitmproxy or Wireshark and replaying them. Decompiling a client with a tool like Ghidra, the NSA's open source reverse engineering framework, is a last resort, both because it is slower and because it carries the most legal risk.

What does AI change about reverse engineering legacy software?

AI tools have made the reading part much cheaper: summarizing unfamiliar code, mapping dependencies, drafting schemas from sample payloads and writing first-pass tests. They have not changed the parts that need judgment or access, and they don't keep an integration working after the vendor ships an update.

On reading and comprehension, the published evidence points one way. Thoughtworks moved "using GenAI to understand legacy codebases" to Adopt on its Technology Radar in November 2025, calling it "a practical default rather than an experiment" and naming tools such as Claude Code, Cursor, Copilot and Aider for finding business rules, summarizing logic and mapping dependencies. Thoughtworks engineers had earlier described their CodeConcise accelerator, which loads a codebase's syntax trees into a graph database for an LLM to explain. Reverse engineering a 10,000-line mainframe module had taken about six weeks, and they estimated the tool "could reduce this by two-thirds, from 6 weeks to 2 weeks for a module," a proof-of-concept estimate by their own account.

Google's engineers published harder numbers on a neighboring task. In 39 code migrations run by three developers over twelve months, 74.45% of the submitted code changes were generated by an LLM, and the developers estimated total migration time fell by half compared with earlier manual migrations. Anthropic's February 2026 post on COBOL modernization argues that understanding old code has been the most expensive step and that a model can map entry points, execution paths and data flows. It is vendor content with no measured outcomes, and it leaves prioritization and validation with the team.

Raw speed is less clear. In METR's July 2025 randomized study, 16 experienced open source developers took 19% longer on tasks where AI was allowed, while believing it had sped them up by about 20%. METR's February 2026 update says current tools are likely faster but its newer data is only very weak evidence of how much. Our reading: AI helps most on large unfamiliar code and least on code the developer already knows.

In our work, the split looks like this:

TaskWhat AI does wellWhat still needs a person
Reading a schema with hundreds of cryptically named tablesProposes what each table holds from names, keys and sample rows; clusters related tablesConfirming each guess by watching the table change during a real transaction
Decoding captured traffic or a file formatSpots structure in hex dumps and XML, drafts a parser, explains encodings such as packed decimal or IBM floatCollecting samples that cover every variant, and deciding when a parser is correct
Understanding old code (RPG, COBOL, VB6, decompiled .NET)Summaries, call graphs, business rules in plain EnglishChecking the summary against behavior; models describe code confidently even when they are wrong
Keeping the integration workingDrafting fixes once a change is detectedDetection itself, which comes from validation and monitoring
Access, contracts and riskSearching a long MSA for relevant clausesThe legal decision, and deciding what vendor material may go to a hosted AI service at all

Pasting decompiled vendor code or confidential vendor documentation into a hosted AI service may count as disclosure under the confidentiality clause in your license, as our article on whether reverse engineering software is legal explains. Use a model your contract allows, or keep that material out of prompts.

Why do unofficial integrations break, and how do you make one last?

Unofficial integrations break when the vendor changes something they silently depended on, such as a new enum value, a renamed field or a changed session timeout. They last when every assumption is a test or schema that fails loudly the day it stops being true.

AI makes the first working version cheaper. Surviving the vendor update nobody told you about depends on ordinary engineering:

  • Tests for every operation you depend on. Pact describes contract testing as checking "an integration point by checking each application in isolation," but its consumer-driven model assumes the provider runs your contracts, which a legacy vendor won't. The workable substitute is weaker: tests against recorded vendor responses, plus live probes that run against a test instance after every vendor update.
  • Schema validation on every response, as in the code above, with quarantine instead of best-effort parsing.
  • Monitoring on volumes and shapes, such as row counts per sync, null rates and new coded values. In our education pipeline, a 40% drop in daily attendance records raises an alert even if every record parses.
  • Versioned schemas and a changelog, so a vendor change becomes a reviewed code change instead of a hotfix.
  • Least privilege: a read-only database account scoped to the tables you need, credentials in a secrets manager, and the same controls on the pipeline as on the source when it carries patient, student or payroll data.

For the CRM project, the case study reports zero production incidents from undocumented behavior since deployment, and an estimated 60% to 70% less integration time for new features that touch the CRM.

Building Healthcare Software?

Get a free architecture review for your HIPAA-compliant application. We've built 20+ healthcare systems.

Download: 2026 HIPAA Compliance Checklist

14-page developer-focused checklist covering Privacy Rule, Security Rule, and Breach Notification requirements — plus 10 AI prompts for executive compliance verification.

No spam. We respect your privacy.

Do you need middleware or an iPaaS for legacy integration?

Not always. An integration platform or message broker earns its cost when many systems exchange data in many directions; for one or two legacy systems feeding a few consumers, an owned API layer and a queue are usually enough. A platform connector still needs someone to work out what the legacy data means.

Decide on timing before tooling. Reporting and analytics can usually live with batch loads; order entry and anything a customer sees tend to need events. The education pipeline ran both: under three minutes for webhook sources, 12 to 15 minutes for scheduled ones. Settle source of truth early too: if two systems can edit the same customer or student, one has to win, and the table mapping their IDs becomes one you guard carefully.

How do you extract data from a legacy system without downtime?

Read from a copy, not from the live system, and move changes incrementally. The usual sequence is change capture switched on first, a snapshot or replica for the bulk history, replay of the overlap, and a parallel run before anything downstream depends on the new feed.

  1. Start capturing changes before you copy history. Use the system's own change mechanism where one exists. On SQL Server, change data capture reads inserts, updates and deletes from the transaction log into change tables. Enabling it adds a cdc schema and SQL Server Agent jobs to the vendor's database and keeps three days of changes by default, so check support terms and size retention to your schedule. CDC is available in Standard edition only from SQL Server 2016 SP1; older Standard instances can use change tracking, which every edition has.
  2. Take the history from a copy. Restore a backup taken after capture started, or use a read replica if support terms allow, so heavy queries never touch production. Replay changes captured since the backup point and deduplicate by primary key.
  3. Where you can't add anything to the database, use watermarks, and know their limits. A monotonically increasing key catches inserts only. A reliably maintained last-modified column catches inserts and updates. Neither catches hard deletes, so add a periodic keyed comparison (hash rows by primary key and diff) or use a soft-delete flag if one exists. Store the watermark yourself and overlap windows slightly.
  4. Run in parallel. Feed the new pipeline while the old process keeps running, and reconcile counts, totals and keyed hashes daily, since a delete offset by an insert leaves counts unchanged. Agree in advance what level of divergence stops the cutover and how you fall back. Our education pipeline rolled out district by district over six weeks, alongside the legacy system.
  5. Cut over by unit. Move one plant line, one district or one department at a time, at a natural break such as a shift change, a term boundary or a month-end close.

Writes are the exception. If the integration must create orders or update records, send them through the vendor's supported API or interface, or through the application's own import routine, so its validation and audit logic run. UI automation is the fallback when nothing else accepts writes. Don't write to the tables directly, even for one-off fixes.

Should you keep, wrap or replace a legacy system?

Keep the system when it works and only needs data out. Wrap it with an owned API when several new tools need to talk to it. Replace it in pieces, using the strangler fig pattern, when the vendor's roadmap, cost or risk makes staying untenable. We treat a full rip-and-replace as the last option.

Martin Fowler's strangler fig is the gradual route: new code starts with small additions and takes over behavior from the legacy system piece by piece. The owned layer from step four makes that practical, because callers stop knowing which system answered.

SituationKeep (integrate in place)Wrap (owned API layer)Replace (strangler fig)
The system does its job; you need reports or one feedYes: read from a replica or exportOptionalNo
Several tools need the same data or actionsGets brittle fastYesNot yet
Vendor has announced end of on-prem development or supportShort term onlyYes, to decouple callers before the movePlan it, module by module
License cost rises faster than the value you getNoYesReplace the modules you use least first
Nobody left understands the systemRiskyYes, after documenting it with the four stepsLikely, once documented
Security or compliance exposure you cannot fix in placeNoAs a bridgeYes
The system holds history but no new transactionsRead-only, for a whileNoArchive the data and retire it

Wrapping first means a later replacement swaps one adapter instead of rewriting every caller. Data migration, ID mapping and cutover still have to happen, but a vendor's deadline stops being a deadline for every connected system at once.

Is it legal to reverse engineer legacy software?

Often, yes, but in the US the license agreement is usually the deciding constraint. Courts have treated reverse engineering for interoperability as fair use, and the DMCA has a narrow interoperability exemption, yet courts have also enforced contract clauses that ban reverse engineering. This is not legal advice; review your license agreement and MSA with counsel.

RuleWhat it says, briefly
Copyright fair useIn Sega v. Accolade (1992), the Ninth Circuit held that disassembly to reach functional elements can be fair use when it is the only way to get them
DMCA 1201(f)17 U.S.C. 1201(f) lets someone with a lawful right to use a program circumvent protection only to identify elements needed for interoperability of an independently created program, when those elements were not already readily available and the acts do not otherwise infringe
ContractNo-reverse-engineering clauses have been enforced, from Bowers v. Baystate (2003) to Versata v. Ford, where the license barred reverse engineering and the Federal Circuit reinstated an $82,260,000 contract award in 2026
CFAAMatters when you probe a vendor-hosted system; Van Buren (2021) framed it as whether you may enter that part of the system at all
EU Software DirectiveArticle 6 allows a licensee to decompile for interoperability under strict conditions, and Article 8 voids contract terms that override it

Reading your own database and parsing your own exports carry the least risk; decompiling, defeating license checks and distributing tools carry the most. Our legal guide to reverse engineering software has the cases, a risk table by technique and our pre-project contract checklist.

How much does legacy system integration cost, and how long does it take?

On our published ranges, a single integration against a documented API takes 40 to 80 hours, and undocumented or legacy SOAP integrations routinely take two to three times their estimate. Whole projects start from base ranges of $80,000 to $300,000 for enterprise integration and $100,000 to $400,000 for legacy modernization, before adjustments for complexity, compliance and schedule.

The figures come from our custom software cost calculator, built from our project history:

ItemPublished range
Discovery (inventory, data flow mapping, integration discovery, phased plan)$8,000 to $25,000
Simple REST integration with good documentation40 to 80 hours
EHR integration (Epic, Cerner), including vendor onboarding200 to 600 hours
Legacy SOAP or undocumented vendor APIOften 2 to 3 times the estimate
Enterprise integration or custom system (calculator base)$80,000 to $300,000
Legacy modernization (calculator base)$100,000 to $400,000
Legacy SCADA or MES modernization$150,000 to $400,000

The calculator's standard schedule is three to six months; compressing a project below three months costs more because more engineers work in parallel. AI should eventually move the 2x to 3x multiplier on undocumented systems. On recent projects it has shortened discovery noticeably, but we haven't measured that rigorously enough to change the published number. Vendor onboarding, user acceptance and parallel runs depend on other people's calendars and haven't gotten faster.

Running costs matter too. The education pipeline cut infrastructure from $8,500 to $340 a month, transformation errors from 3.8% to 0.02%, and developer time to onboard a district from six weeks to five days. For a healthcare-specific breakdown, see what an HL7 interface costs.

Legacy system integration examples by industry

Each article below applies the surfaces and method to one vendor or deadline.

Manufacturing

Education

Oil and gas

Healthcare

Where to start

Pick the one system that causes the most manual work, and write down which surfaces from the table above you can reach today, what your license says about reverse engineering and direct database access, and which two or three data flows would remove the most re-keying. Add who depends on it and how long it can be down. That is enough to start the keep, wrap or replace decision and to scope an estimate.

Our legacy system modernization work starts with that inventory, and you can talk to us about one system before committing to more.

Download: 2026 HIPAA Compliance Checklist

14-page developer-focused checklist covering Privacy Rule, Security Rule, and Breach Notification requirements — plus 10 AI prompts for executive compliance verification.

No spam. We respect your privacy.

Daniel Ashcraft

Healthcare & Compliance

Founder & Lead Engineer at Of Ash and Fire. Building custom software for healthcare, education, and manufacturing.

Founder & Lead Developer at Of Ash and Fire · Test Double alumni · Former President, Techlahoma Foundation

12+ years building HIPAA-compliant software for healthcare organizations, including EHR integrations (Epic, Cerner), telemedicine platforms, and clinical decision support systems.

Frequently Asked Questions

What is legacy system integration?+
Legacy system integration is connecting older software a business still depends on, such as an on-premise ERP, a student information system or an older EHR, to newer applications so data moves between them. When the vendor offers no usable API, the interface is reverse engineered from the database, files, network traffic or screens and wrapped in an API the company owns.
What are the main legacy system integration challenges?+
The usual challenges are an undocumented schema or API, business logic that lives in application code that direct table writes would bypass, vendor APIs limited to cloud customers or paid modules, license clauses that restrict reverse engineering or direct database access, and vendor updates that silently change data shapes. Schema validation, tests and monitoring catch the last one.
How do you extract data from a legacy system without downtime?+
Start change data capture or a stored watermark first, then load the bulk history from a restored backup or read replica so heavy queries never touch production, and replay the overlap. Handle hard deletes with change capture or a periodic keyed comparison. Run the new feed in parallel, reconcile daily, and cut over one site or department at a time.
How has AI changed reverse engineering legacy software?+
AI tools make reading unfamiliar code, schemas and captured traffic much faster, and Thoughtworks now treats GenAI for understanding legacy codebases as a default practice. They do not confirm that a guess about a table or message is correct, decide what vendor material may be shared with a hosted model, or notice when a vendor update changes the data.
Is it legal to reverse engineer software to integrate with it?+
Often, yes. US courts have treated reverse engineering for interoperability as fair use, and DMCA section 1201(f) has a narrow interoperability exemption, but courts have also enforced license clauses that ban reverse engineering. EU law voids contract terms that override the right to decompile for interoperability. This is not legal advice; review your license agreement and MSA with counsel.
How much does legacy system integration cost?+
On our published ranges, a documented REST integration takes 40 to 80 hours, and undocumented or legacy SOAP integrations often take two to three times their estimate. Project base ranges are $80,000 to $300,000 for enterprise integration and $100,000 to $400,000 for legacy modernization before adjustments. Discovery, which maps the systems and data flows first, runs $8,000 to $25,000.

Need HIPAA-Compliant Software?

We build healthcare applications that meet strict compliance requirements — from EHR integrations to telemedicine platforms. 12+ years of regulated-industry experience.