Technical

10 Things Software Engineers Learn the Hard Way on Their First Health Data Integration

Health data looks like any other data until real reports start arriving. Here is what tends to surprise engineering teams after launch, and what to check before it surprises yours.

Suhina Singh
Nan Kyaw Thae Su
Full Stack Developer
October 2, 2026
·
10 min read

If you have built integrations for payments, logistics or e-commerce, you already know how to move data reliably between systems. Health data asks for all of that and then adds a layer that is easy to underestimate: the meaning of a value depends on context that is often missing, inconsistent or buried in a document. A number can be perfectly transmitted and still be wrong for the person reading it.

None of the lessons below are exotic. They are the issues we see most often when teams move from a clean demo file to the reports their users actually send. Each section describes the problem, shows a short example, and ends with a check you can run against your own design.

 

At a glance

01The same test has many names
02A number without its unit is not a result
03Reference ranges belong to the lab, not the test
04Not every result is a number
05One report carries several dates
06Results get corrected and reissued
07Patient matching is harder than it looks
08Most data still arrives as documents
09Standards are a destination, not a guarantee
10Privacy starts in your own logs

 

1. The same test has many names

Laboratories name tests for their own convenience, and those names change across labs, countries, languages and even analyser models within the same lab. A fasting glucose result can arrive under half a dozen labels, and a string match on "Glucose" will quietly merge it with random glucose, urine glucose and glucose tolerance results, which mean very different things clinically.

Fasting glucose FBS GLU-F Glucose (F) FPG Fasting plasma glucose Glukosa puasa

Six labels, one test. Your system needs to know they are the same thing, and that "Glucose, random" is not.

 

The practical fix is to identify results by what was measured, in what specimen and under what conditions, and to map each lab's local names to medical coding standards (plus any local code set your organisation maintains) rather than trusting the display name.

Check: if two labs send the same test under different names, will your system recognise them as one? If one lab sends two different tests under similar names, will it keep them apart?

 

2. A number without its unit is not a result

Glucose of 5.4 is normal in millimoles per litre (mmol/L), the unit used in much of Asia, Europe and Australia, while 5.4 in milligrams per decilitre (mg/dL), common in the United States, would be dangerously low. Creatinine is reported in micromoles per litre in some countries and milligrams per decilitre in others, with a conversion factor of 88.4 between them. Glycated haemoglobin (HbA1c) is reported as a percentage in some labs and in mmol/mol in others, so 6.5% and 48 mmol/mol describe the same result1.

What often arrives

{ "test": "Glucose", "value": 5.4 }

What your system needs to keep

{
 "test": "Glucose, fasting",
 "value": 5.4,
 "unit": "mmol/L",
 "reference_range": { "low": 3.9, "high": 5.5, "unit": "mmol/L" }
}

If your product converts units for display or for trend charts, store the original value and unit alongside the converted one, so you can always trace back what the lab actually reported.

Check: can a value ever reach your database, a chart or an AI prompt without its unit attached?

 

3. Reference ranges belong to the lab, not the test

It is tempting to hard-code "normal" ranges per test. In practice, laboratories are expected to establish or verify reference intervals for their own methods and populations2, and ranges often differ by age, sex and pregnancy status. Two labs can report the same value with different flags, and both can be right.

The safer pattern is to store the reference range the lab printed with each result, together with the lab's own high or low flag, and only fall back to a generic range when none was provided, clearly marked as such.

Check: if a user uploads reports from two labs, will your app flag the same value consistently with what each lab actually said?

 

4. Not every result is a number

Real reports contain values such as <5, >1000, Trace, Positive, Not detected and See comment. A column typed as a decimal will either reject these or, worse, silently turn <5 into 5. Fast Healthcare Interoperability Resources (FHIR), the most widely adopted modern standard for exchanging health data, handles this with a comparator on quantities and separate fields for text or coded answers3.

Keeping "less than 5" meaningful

"valueQuantity": { "comparator": "<", "value": 5, "unit": "mIU/L" }

A qualitative result

"valueString": "Trace"

Check: what does your system store when a lab sends "<5", and what does your chart draw for it?

 

5. One report carries several dates

A single lab report can include when the specimen was collected, when the lab received it, when the result was reported and when it was amended. For trends and clinical decisions, the collection date is usually the one that matters, yet it is often the least prominent date on the page. Date formats add another trap: 03/04/2026 is 3 April in Singapore and 4 March in the United States.

CollectedUse for trends ReceivedLab logistics ReportedResult released AmendedVersion changed MOST IMPORTANT

Four dates, four meanings. Picking the wrong one shifts every point on a trend chart.

 

Check: does your data model keep each date separately, and do you know which date format each source uses?

 

6. Results get corrected and reissued

Labs correct results after release, for example when a sample is found to be haemolysed or a transcription error is caught. Both FHIR and HL7 Version 2 (the older messaging standard still used by most laboratory systems) carry a status for each result, such as preliminary, final, amended or corrected4, 5. If your integration inserts every message as a new row, a corrected result sits next to the wrong one and both appear in the patient's history.

Same result, second version

{
 "resourceType": "Observation",
 "identifier": [{ "value": "LAB-88213-GLU" }],
 "status": "corrected",
 ...
}

Use the lab's own identifier to update the existing result, keep the earlier version for audit, and decide how you will tell users (and clinicians) that something they saw has changed.

Check: what happens in your system when the same result arrives twice with different values?

 

7. Patient matching is harder than it looks

There is rarely a single identifier that every system shares. Naming conventions vary widely: many people across Asia write the family name first, some people have a single name, and names are transliterated differently between scripts. Dates of birth are sometimes estimated or recorded in a different calendar. A report can easily be attached to the wrong person, or a person can end up split across two records.

Design for this early. Decide which identifiers you require, what counts as a confident match, and what happens to a report when the match is uncertain. A queue for human review is far cheaper than an incorrect result in someone's record.

Check: where does a report go when your system is not sure who it belongs to?

 

8. Most data still arrives as documents

Even where lab systems exchange structured messages internally, a large share of results reach digital health products as PDFs, scanned letters, emailed attachments and phone photos of paper reports. These arrive rotated, multi-page, in several languages, with tables that break across pages and handwritten notes in the margin.

Large language models make a first pass at extraction look easy on a clean sample. The difficulty shows up at volume: a value attached to the wrong test, a unit read from the adjacent column, a row skipped on page two. Whatever approach you use, you need a way to measure accuracy at field level and a route for uncertain extractions to be reviewed by someone clinically trained.

Check: do you know your field-level accuracy on real-world documents, and who reviews the results your system is unsure about?

 

9. Standards are a destination, not a guarantee

Receiving data "in FHIR" or "in HL7" is a good start, but it does not mean two sources look the same. FHIR is designed to be adapted through profiles and extensions, so implementations differ in which fields they fill and how6. HL7 Version 2 feeds vary by site, often include custom segments, and put the same information in different fields. Many institutions also maintain their own code sets alongside national or international ones.

Treat each new source as its own integration. Ask for sample messages early, document how that source uses each field, and expect to map its local codes and conventions before the data is consistent with the rest of your system.

Check: if you added a second lab tomorrow, how much of your parsing and mapping would you need to redo?

 

10. Privacy starts in your own logs

Teams usually protect the production database well. Health data tends to leak through the side doors: request bodies written to application logs, error-tracking tools capturing payloads, real reports copied into test fixtures, screenshots in support tickets, and prompts sent to third-party AI services. Many jurisdictions also have rules about where health data may be processed, which affects which cloud regions and vendors you can use.

Pseudonymise identifiers before data reaches logs, prompts and test environments, use synthetic reports for development, and know the processing location of every service in your pipeline. We will go deeper on these patterns in a later guide in this series.

Check: search your logs and error tracker for a real patient name or date of birth. What do you find?

 

Bringing it together

None of these lessons require exotic technology. They require treating context as part of the data: the unit, the range, the date, the status, the source and the person the result belongs to. Teams that plan for this before launch spend their time building features. Teams that meet it after launch spend months cleaning up records their users already trusted.

 

How Jonda Health can help

You do not have to solve every one of these problems in-house. There are two ways we can support your team.

JondaX: make your data usable

One API for every source. Send lab reports, device photos, HL7 v2 or FHIR, and receive structured, standardised results in the format your system needs, with units, ranges and your own terminology preserved. Results that need a second look are reviewed by clinically trained reviewers, with 99% field-level accuracy with expert review. ISO 27001 certified and designed to comply with HIPAA, GDPR and PDPA.

Read the Quickstart Connect the MCP Server

Jonda Health Services: plan it right

If you are earlier in the journey, our Health Data Foundations work helps you assess your sources, design your data model and plan integrations before they become rework, drawing on experience across clinical practice, interoperability, product and AI.

Explore Jonda Health Services

Not sure where to start? Book a free 30-minute data readiness conversation and we will talk through your sources, your product and where the risks are.

Get in touch: hello@jonda.health

 

References

  1. Hanas R, John G, on behalf of the International HbA1c Consensus Committee. 2010 consensus statement on the worldwide standardization of the hemoglobin A1C measurement. Diabetes Care. 2010;33(8):1903-1904.
  2. Clinical and Laboratory Standards Institute. Defining, Establishing, and Verifying Reference Intervals in the Clinical Laboratory; Approved Guideline, Third Edition. CLSI document EP28-A3c. Wayne, PA: CLSI; 2010.
  3. HL7 International. FHIR R4, Data Types: Quantity (comparator). hl7.org/fhir/R4/datatypes.html
  4. HL7 International. FHIR R4, Observation resource (status). hl7.org/fhir/R4/observation.html
  5. HL7 International. HL7 Version 2.5.1, Chapter 7: Observations (OBX-11 Observation Result Status).
  6. HL7 International. FHIR R4, Profiling FHIR. hl7.org/fhir/R4/profiling.html

Code examples are illustrative and simplified. Reference ranges shown are examples only and are not clinical guidance.

Try JondaX free

30 free transformations. No credit card required.