Skip to content
Zowork
All case studies
Case study~8 min read

Reverse-engineering a 16-year-old behavioral-health EHR.

Some software has been in production longer than the team maintaining it. We embedded into a sixteen-year-old electronic health record platform, built on a proprietary language with no public documentation, to fix long-standing bugs and ship the clinical, billing and scheduling features behavioral-health agencies run every day.

Legacy SystemsEHRHealthcareRoot-cause Engineering
legacy_routing_logic.sqlhundreds of lines
1CREATE PROCEDURE legacy_routing_logic
2 @incoming RESULT SET
3AS BEGIN
4 -- parse the incoming lab result
5 ;WITH parsed AS (
6 SELECT ... one row per order,
7 correctly partitioned ...fix
8 -- the fix: read the data in
9 -- the shape it actually arrives )
10 WHERE match(result, dashboard) = 1format mismatch
11END
root cause · result-format mismatch
Introduction

Sixteen years of software, zero Stack Overflow answers

The platform is a comprehensive behavioral-health EHR, sixteen years of evolution shaped by the direct input of providers, county-based networks and managed-care authorities. It is exactly the kind of system that runs quietly under thousands of clinicians and is far too entangled to rip out and replace.

The client, a US-based IT partner to health-services providers and organisations, brought us in to extend and harden it. The catch: a major part of its business logic runs on a proprietary language you cannot Google, and the rest lives deep in the database, in logic hundreds of lines deep.

The brief

One system for everything an agency does

EHR adoption is effectively mandatory in the US, where CMS led the transition with incentives. Behavioral-health agencies needed the dozen things they do every day centralised into a single platform.

  • Schedule patients with the right therapist and send email / text reminders.
  • Capture every session’s progress in one place: notes, diagnoses, treatment plans, forms.
  • Store billing against current authorisation criteria, ready to claim.
  • Order labs electronically and route the results back to the clinician’s dashboard.
The platform

The modules we worked across

A complex, role-aware system where authorisations drive what can be claimed, and every module feeds the next.

Clinical

Charting, progress notes, treatment plans with goals & objectives, diagnoses.

Billing

Claim authorisation, claim creation & submission, procedure code sets.

Scheduling

Appointments driven by therapist work schedules and service types.

Reports

Custom clinical and billing reports, printable for hand-off.

Medication management

Allergy classification and medications prescribed to patients.

eLabs ordering

Electronic lab orders with results routed back to the clinician.

The hard part

Learning a language the internet had never heard of

The platform’s screens and business logic (active-client lists, remaining authorisations, units, durations, unsigned-note counts) are written in a proprietary, object-oriented language. The rest of the behaviour sits in the database, in logic that had grown for sixteen years.

There is no public documentation. No articles, no Stack Overflow, nothing on the web. Our entire knowledge base was a couple of internal documents and a patient US team willing to answer questions. So we did what you do with any black box: read it, instrument it, and rebuild the mental model from first principles, with daily standups and weekly deep-dives to compare notes.

Where the knowledge lived
No documentation. No articles. No Stack Overflow. A couple of internal documents and a generous team were the whole map. So we drew our own, debugging through hundreds of lines of legacy logic to learn how each module actually worked.
Root-cause deep-dive

The bug nobody could find

When we picked it up, electronic lab orders were created fine, but the results never made it back to the clinician's dashboard.

The routing lived in one enormous, undocumented block of legacy logic. It took us three days, as a team, to map the data flow (what it was doing and where) before we could even name the bug. The root cause: the results were arriving in one shape, and the system was reading them in another, so nothing ever matched and nothing ever routed.

We fixed it at the source: aligned the system with the format the results actually arrive in, and cleaned up how the incoming data was split apart, so each order gets exactly the result that belongs to it. The fix also made the whole path faster.

BeforeAfter
Result matchingRead in the wrong shape, so nothing matchedAligned with how results actually arrive
Result routingResults never reached the dashboardEvery result lands with its order
Clinician experienceChasing labs by phone and faxResults on the dashboard, automatically, faster than before
Delivered

What we shipped into it

Once the model clicked, the features came, including a few the team had been putting off.

The deep-end form

One of the most complex screens in the platform, composed of many interdependent windows. Slow to build, but it burned the platform’s structure into muscle memory and made everything after it faster.

Authorisation calculations

Progress-note authorisation math that honours every billing scenario, so agencies claim correctly the first time.

Coverage / maintenance window

When a therapist is on leave or moves on, reassign their tasks, appointments, notes-for-review, unsigned forms and billing to other staff, so no work falls through the cracks.

A faster delivery loop

We helped the team add a process-improvement step to the project lifecycle that lifted developer experience and cycle time across the team.

Outcome

A legacy platform, modernised from the inside

16-yr

Legacy EHR codebase we embedded into and extended

3 days

To map an undocumented data flow before the root cause had a name

then one clean fix
6

EHR modules we worked across or extended

clinical → billing → labs
  • A comprehensive EHR that streamlines enrolment and treatment for behavioral-health agencies.
  • One stop to schedule, document, add guarantors and file claims against authorisations, diagnoses and medications.
  • Lab results that reach the clinician automatically, after years of not arriving at all.
  • Report generation that lets agencies print and hand off the right patient information.
Conclusion

Legacy isn't a liability if you're willing to read the code

The instinct with a sixteen-year-old, undocumented system is to quarantine it. But the fastest path to value was the unglamorous one: read it carefully, instrument it, learn its language on its own terms, and fix the real root cause, not paper over it. Done that way, a legacy platform keeps doing its job, only better.

Sitting on a system everyone’s afraid to touch? We’re comfortable in the old code as well as the new.

Talk to engineering