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.
| Surface | Typical examples | What you get | Main risks | Production impact |
|---|---|---|---|---|
| Database | SQL Server under an on-prem ERP, Db2 for i on IBM i, Oracle under a hospital system | Everything the application stores, at full fidelity | Undocumented schema, business logic that lives in application code, support terms that forbid direct access, writes that skip validation | Low for reads from a replica or snapshot; never write directly |
| Files and exports | CSV and fixed-width exports, SFTP drops, report dumps, SEG-Y and other binary formats | Whatever the export includes, on a schedule | Format changes without notice, partial exports, encoding quirks such as EBCDIC | Very low |
| Network or API traffic | SOAP calls between a thick client and its server, an undocumented REST API behind a web app | The same calls the vendor's own client makes, including writes | Undocumented behavior, session handling, encryption you may not be allowed to break | Low if you replay only reads at first |
| Vendor API or SDK | REST v2 on Epicor Kinetic, Blackbaud SKY API, a FHIR endpoint, an OpenAPI spec | Supported, documented operations | Coverage gaps, rate limits, availability tied to a hosting tier or a paid module | Low; this is the supported path |
| Message queues and interface feeds | HL7 v2 feeds, IBM i data queues, OPC UA, MQTT, EDI | Messages in real time or in batches, depending on the protocol | Interface license fees, message variants, delivery guarantees you have to build yourself | Low once the feed exists |
| User interface automation | 5250 green screens, desktop forms, web pages with no API | Anything a user can see or type | Breaks when a screen changes, slow, hard to make transactional | Moderate; 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:
- 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.
- 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.
- 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.
- 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:
| Task | What AI does well | What still needs a person |
|---|---|---|
| Reading a schema with hundreds of cryptically named tables | Proposes what each table holds from names, keys and sample rows; clusters related tables | Confirming each guess by watching the table change during a real transaction |
| Decoding captured traffic or a file format | Spots structure in hex dumps and XML, drafts a parser, explains encodings such as packed decimal or IBM float | Collecting 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 English | Checking the summary against behavior; models describe code confidently even when they are wrong |
| Keeping the integration working | Drafting fixes once a change is detected | Detection itself, which comes from validation and monitoring |
| Access, contracts and risk | Searching a long MSA for relevant clauses | The 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.
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.
- 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
cdcschema 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. - 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.
- 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.
- 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.
- 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.
| Situation | Keep (integrate in place) | Wrap (owned API layer) | Replace (strangler fig) |
|---|---|---|---|
| The system does its job; you need reports or one feed | Yes: read from a replica or export | Optional | No |
| Several tools need the same data or actions | Gets brittle fast | Yes | Not yet |
| Vendor has announced end of on-prem development or support | Short term only | Yes, to decouple callers before the move | Plan it, module by module |
| License cost rises faster than the value you get | No | Yes | Replace the modules you use least first |
| Nobody left understands the system | Risky | Yes, after documenting it with the four steps | Likely, once documented |
| Security or compliance exposure you cannot fix in place | No | As a bridge | Yes |
| The system holds history but no new transactions | Read-only, for a while | No | Archive 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.
| Rule | What it says, briefly |
|---|---|
| Copyright fair use | In 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 |
| Contract | No-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 |
| CFAA | Matters 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 Directive | Article 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:
| Item | Published range |
|---|---|
| Discovery (inventory, data flow mapping, integration discovery, phased plan) | $8,000 to $25,000 |
| Simple REST integration with good documentation | 40 to 80 hours |
| EHR integration (Epic, Cerner), including vendor onboarding | 200 to 600 hours |
| Legacy SOAP or undocumented vendor API | Often 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
- Epicor Kinetic on-premise after 2028: Kinetic 2028.1 is the final on-premises release, with Active Support through December 31, 2029. Covers hosting options, what breaks in Epicor Cloud, and moving integrations to REST v2, BAQs and Functions.
- AS400 API integration with REST on IBM i: a REST API on IBM i without rewriting RPG, using Integrated Web Services, Db2 for i over JDBC, stored procedures and data queues.
- Getting data out of Wonderware Historian and AVEVA PI: SQL through the INSQL linked server, PI Web API limits, and syncing to TimescaleDB or InfluxDB instead of replacing the historian.
- JobBOSS² API integration: what ECI's public API covers, why ECI supports it only for hosted customers, and how on-premise shops integrate safely.
- SAP ECC 2027 deadline for mid-size manufacturers: mainstream maintenance for ECC on EHP 6 to 8 ends December 31, 2027; compares extended, customer-specific and third-party support and RISE.
- MES integration with ERP and PLCs in legacy plants: ISA-95 boundaries, B2MML messages, PLC protocol maps and a line-by-line rollout without downtime.
Education
- PowerSchool alternatives and data export after the 2024 breach: how the main SIS alternatives compare, what is established about the breach, and the export paths, none of which is a complete archive on its own.
- Skyward Qmlativ migration: what moves from SMS 2.0, what gets rebuilt, how long read-only access lasts and how to keep an archive you own.
- Raiser's Edge database view sunset: Blackbaud ends database view support on September 15, 2027. The article covers which queries, exports and plug-ins break and how to keep donor data flowing through SKY API and backups.
Oil and gas
- The SEG-Y file format explained: a byte-level reference to headers, sample format codes and IBM floating point, with tested conversion code. Our SEG-Y visualization case study uses the same decoding.
- Refinery control system modernization without downtime: a phased plan that moves historians and reporting onto a separate one-way data path first, then migrates consoles and controllers loop by loop, leaving the rest for turnarounds under OSHA process safety management.
Healthcare
- Information blocking and getting your data out of your EHR: what 45 CFR Part 171 requires, where enforcement stands, and how to request a full export under the certified (b)(10) criterion.
- MEDITECH MAGIC end of life and legacy data: what converts to Expanse, which retention rules apply to the history left behind, and how to archive, integrate or retire it.
- What an HL7 interface costs: the line items behind an HL7 v2 interface, from vendor fees to interface engines and testing, and where AI changes the build.
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.