We Built a Mobile App for a 9-Branch Pathology Lab: Reports in 6 Hours, Not 36
A 9-branch pathology lab in Coimbatore replaced a paper-PDF-WhatsApp loop with a React Native app, HL7 ingestion, and a push pipeline. ~28,000 patients, build cost Rs 22L, median report time cut from 36 hours to 6.
K
Khushi Singh
July 16, 202514 min read
0%
A 9-branch pathology lab in Coimbatore was running a strange relay race. A patient gave a sample at branch 4 in Saravanampatti at 9:42 am. The sample physically travelled to the central lab in Peelamedu by 11 am. Results were verified by 1 pm. The PDF report was emailed to the branch at 2 pm. The branch printed it, called the patient, asked them to come collect it, and then forwarded a WhatsApp scan if the patient asked nicely. Median report-in-patient-hand time: 36 hours. We shipped a React Native app + an HL7 ingestion bridge + a push pipeline. The new median: 6 hours. Build cost ₹22 lakh.
9
Branches Across Tamil Nadu
~28K
Active Patients in Year 1
6 hr
New Median Report Delivery (was 36 hr)
Rs 22L
Fixed-Price Build (Phase 1)
## The Answer in 60 Words
We built a React Native 0.74 app (iOS + Android), a Node.js + Fastify API on a Hetzner CCX23, PostgreSQL 16 for the patient/report store, and a Mirth Connect HL7 bridge talking to the lab's existing analyser fleet. Push delivery via Firebase Cloud Messaging with an SMS fallback. ~28,000 active patients in year 1. Median report-in-hand: 6 hours. Build cost ₹22 lakh, run ₹54,000/month.
## Why This Matters Now
Indian diagnostics is a 9.5% YoY growth market and the central question for every chain under 25 branches is: how do we deliver reports to a smartphone the patient already owns, without buying a hospital-grade LIS? Off-the-shelf LIS platforms like LabVantage start at ₹8-12 lakh/year in licences and ship features for 500-bed hospitals that mid-size labs never touch. Generic patient-portal builders ignore HL7. The gap is what we built into.
Two recent shifts widen the case. First, the [DPDP Act 2023](https://amlegals.com/health-data-and-the-dpdp-act-a-practical-guide/) treats health data as sensitive personal data with explicit consent and DPO requirements — a paper-and-WhatsApp workflow is now legally exposed in a way it was not in 2022. Second, [HL7 FHIR adoption in India](https://healthcareintegrations.com/hl7-vs-fhir-which-standard-should-you-prioritize-in-2025/) accelerated through 2024-25; analyser vendors that did not speak FHIR three years ago now ship it as standard.
## The Client (Specific Details)
- Sector: Pathology + radiology diagnostics chain (NABL-accredited)
- Locations: 9 branches across Coimbatore, Tirupur, Erode, Salem
- Central lab: Peelamedu, Coimbatore — handles 100% of high-volume processing
- Test mix: 78% biochemistry/haematology (CBC, LFT, KFT, lipid, sugar), 14% microbiology, 8% radiology
- Daily volume: 1,840 reports/day at peak (winter season), 1,200 average
- Analyser fleet: 11 instruments — Sysmex XN-550, Cobas c311, Architect ci4100, others
- Patient demographic: ~62% over 50 years old, ~38% smartphone-first under 50
- The trigger: A NABL surveillance audit in March 2025 flagged the WhatsApp PDF distribution as inadequate consent capture. Owner gave us 14 weeks.
## The Architecture (One Diagram Worth Drawing)
RN
Mobile: React Native 0.74
One codebase for iOS + Android. Login via OTP to the registered mobile, biometric unlock for repeat opens. Reports are PDF + a structured-data view (so the senior who only wants the haemoglobin number sees it big).
HL7
HL7 Bridge: Mirth Connect
Listens for HL7 v2.5 ORU^R01 messages from the analyser fleet, normalises to a common JSON shape, posts to our API. Mirth chosen over Iguana because it is open-source.
API
API + DB: Fastify + PostgreSQL 16
Patient, sample, report, audit, consent tables. Reports stored as both binary PDF and structured JSON for trend graphs. ~14 GB total data after year 1.
PUSH
Push: FCM + SMS Fallback
Firebase Cloud Messaging for primary push. If the device has not opened the app in 14 days, fall back to SMS with a deep link. ~92% delivery rate; the failures are mostly switched-off phones.
## The HL7 Ingestion Layer (Where the Time Got Spent)
The single most engineering-intensive piece was the HL7 bridge. Lab analysers speak HL7 v2.x — a tab-delimited, pipe-segmented format from 1988 that is still the lingua franca of pathology hardware. A typical CBC result message looks like this:
Mirth Connect parses this into a JavaScript object inside a transformer. We then map analyser-specific test codes to the lab's canonical test catalogue (the Sysmex calls it HGB, the Cobas calls it HB), validate units, and post a normalised JSON payload to our API.
The hard parts were:
- Code mapping for 247 distinct tests across 11 analysers. No vendor agreement on naming. We built a YAML mapping the lab's senior pathologist signed off on. This took 3.5 weeks alone.
- Reference range handling. Ranges differ by age, sex, sometimes by season. We store ranges per (test_code, age_band, sex) and look up at result-ingest time, not at display time.
- Verification workflow. A pathologist must verify every report before it is released to the patient. The HL7 message arrives "preliminary"; only after sign-off in the LIS does the app show "FINAL".
- Image attachments. Radiology DICOM images get a separate ingestion path via a dedicated Mirth channel. The app shows a low-res thumbnail; full DICOM goes to the doctor's portal.
We open-sourced the HL7 → JSON mapping helper at the lab's request — it is a thin wrapper around [HL7-FHIR.org's published guidance](https://www.hl7.org/) that handles the Indian-test-code idiom that is not in the standard.
## The DIY Walkthrough: Build the Lab-to-Phone Loop Yourself
The reference build below is what we ship to two-branch labs as a starter. It is not the full 9-branch system — it is the minimum runnable version that delivers HL7-to-phone in under a working week.
1
Stand up Mirth Connect on a small VM
Install Mirth Connect 4.5 on a 4-core / 8 GB Hetzner box. Open TCP port 6661 for MLLP (the HL7 transport). Configure one channel per analyser model. Use the built-in HL7 v2.x reader, then a JavaScript transformer to convert each OBX segment to your canonical JSON.
2
Build the canonical test catalogue
Sit with your senior pathologist for 4 hours. Walk through every test the lab runs. For each, capture: canonical name, unit, reference range by age band, LOINC code if available. Store in a YAML or DB table. This is the artifact you will live with for years; spend the time.
3
React Native shell with OTP auth
Use react-native-otp-verify for Android auto-read of the OTP SMS. iOS auto-fill works out of the box. Persist the auth token in react-native-keychain (encrypted Keystore on Android, Keychain on iOS). Set token TTL to 30 days; biometric re-auth on every cold open.
4
Report list + report viewer screens
List screen: latest 20 reports, infinite scroll, search bar. Detail screen: PDF viewer (use react-native-pdf) plus a "key results" section above the fold showing the 3-5 most clinically important values with colour-coded ranges. Older patients almost universally prefer the key-results view to the full PDF.
5
Push pipeline with SMS fallback
Wire FCM via @react-native-firebase/messaging. On report-ready, send a push. Maintain a last_app_open timestamp; if older than 14 days, also fire an SMS via your SMS provider (Twilio, Gupshup, MSG91 — we use Gupshup for India). The SMS contains a deep link that opens the app to the report.
6
DPDP-grade consent capture
First-launch consent screen with explicit toggles for: data storage, data retention period, optional research-use opt-in. Persist consent with timestamp + app version + checksum. The consent record itself is signed with HMAC and stored separately so it cannot be silently rewritten.
## The 6-Hour Number (How We Got There)
The 36-hour baseline was the median, not the worst case. The new 6-hour median came from compressing four steps:
The biggest single saving was cutting the patient-travel-to-branch step. ~74% of patients now read the report on their phone within 4 hours of the push and never visit the branch to collect a printout. The lab still prints physical copies for the 26% who request one (largely older patients) but the volume of printed reports has dropped 73%.
## Common Mistakes (Each One Hurts)
Symptom: "Push delivery rate is 60%." Cause: device-token churn (users reinstall, switch phones). Fix: maintain device tokens with a TTL, refresh on every app open, and always have an SMS fallback for stale tokens. Our SMS-fallback rule fires automatically after 14 days of no app open.
Symptom: "Older patients cannot find their report." Cause: too many tabs and filters. Fix: latest report goes on the home screen as a single card. Search and history are one tap away. We removed three navigational layers from the v1 design after a usability test with 14 patients aged 58-82.
Symptom: "HL7 messages occasionally arrive with the wrong patient ID." Cause: an analyser was rebooted and reverted to a default lab ID. Fix: validate every incoming HL7 against the patient registry; quarantine on mismatch and alert the duty pathologist. We catch ~3 such per month — never auto-route them.
Symptom: "The pathologist verified the report but the patient never got the push." Cause: the LIS sends the "preliminary" HL7 first and the "final" HL7 only on sign-off. Our app initially fired push on preliminary. Fix: only send push on a message with OBR-25 = 'F' (final). Catch this in a unit test on the ingest worker.
Symptom: "Patient asks: where is my old report from 2023?" Cause: data retention policy. Fix: agree the retention period in writing with the lab owner. We default to 7 years (NABL guidance) but expose this in the consent screen.
## When Not to Build This
Skip if (a) your daily report volume is under 80 — the build cost will not pay back against off-the-shelf patient portals like CrelioHealth or BookMyTest, (b) you do not own the LIS — without HL7 access from your analysers, the app reduces to a glorified PDF inbox, or (c) you are a single-branch lab — a WhatsApp Business API setup will deliver 80% of the value at 10% of the build cost. Custom apps reward multi-branch operators with mature HL7 infrastructure.
## Real Outcome (12 Months Post-Launch)
~28K
Active App Users
73%
Reduction in Printed Reports
+22%
Repeat-Visit Rate (12-month)
4.6 stars
Play Store Rating (1,940 reviews)
The repeat-visit lift mattered most to the owner. Diagnostics is a high-churn business — patients try whichever lab is closest. A patient who downloads your app and gets their reports there is materially less likely to switch. The lab's marketing team now leads with "get your reports on our app" in their flyers.
## A Detail That Saved Us On Day 23
On day 23 of UAT, a patient called the branch saying "the haemoglobin in my report is wrong, I am young and healthy." The number was correct (12.4 g/dL) but the reference range shown was for an adult male (13-17). The patient was a 32-year-old female; her correct range was 12-15 and 12.4 was normal. We had not wired the sex-specific reference range lookup correctly. Worse, the colour-coded "low" indicator had alarmed her unnecessarily.
We shipped a hot-fix that night and added a regression test that synthesises 200 fake reports across age x sex combinations and asserts the displayed range matches the canonical catalogue. Eight months later we have not had a similar incident, and the senior pathologist signs off on every range-table change with a green-pen ceremony she made up herself.
The lesson: medical-display bugs are not just bugs. They scare people. Test the displayed values, not just the stored values.
## The Stack Cost Per Month (Real Numbers)
| Component | Monthly cost | Notes |
|---|---|---|
| Hetzner CCX23 (app + Postgres) | Rs 3,800 | Right-sized for 1,840 daily reports |
| Hetzner CX22 (Mirth Connect) | Rs 740 | HL7 bridge box, isolated from app |
| Backup S3 (Cloudflare R2) | Rs 1,400 | 14 GB hot + 90-day retention |
| Firebase FCM | Rs 0 | Free tier covers our volume |
| Gupshup SMS fallback | Rs 12,000 | ~9,000 SMS/month for stale tokens |
| Apple Developer Program | Rs 833 | Rs 9,900/year amortised |
| Google Play Console | Rs 208 | Rs 2,500 once-only amortised over 12 months |
| Sentry (errors) | Rs 2,800 | Team plan |
| Engineering retainer (0.4 FTE) | Rs 28,000 | Covers app updates + Mirth changes |
| Compliance + DPO retainer | Rs 4,800 | External DPO advisory hours |
| Total | ~Rs 54,000 | vs Rs 1.2 lakh+/month for off-the-shelf LIS |
## A Note on the TalkDrill Mobile Parallels
We carried two patterns directly from our work on [TalkDrill](https://talkdrill.com), our in-house English-fluency app with 5,000+ active users built on the same React Native stack. First, the FCM + SMS fallback pattern — TalkDrill's voice-session reminders use the same logic and we reused the worker code with minor adjustment. Second, the cold-start biometric re-auth — patients open this app weekly at most, so the cold-start UX has to be as friction-light as TalkDrill's daily users expect. The lab patient is older but the design principle holds: assume the user does not remember their password, design accordingly.
For our deeper engineering write-up on the React Native side of TalkDrill, see [TalkDrill's voice AI 800ms latency on 4G](/blog/talkdrill-voice-ai-800ms-latency-mobile-webrtc-whisper).
The honest caveat on HL7: HL7 v2.x is messy. The standard allows enough flexibility that "compliant" implementations from two vendors can still need translation. Budget 30-40% of your engineering time for the bridge layer. Pretending this away is the single most common project-blow-up we have seen in healthcare IT.
## FAQ
### Is HL7 v2 still relevant or should I jump to FHIR?
Both. Most analyser hardware in Indian labs through 2025 still emits HL7 v2.5; a Mirth or NextGen Healthcare Connect bridge is the realistic path. FHIR is the future for health-record interoperability across systems but adoption inside lab analysers is still uneven. We translate HL7 v2 inputs to a FHIR-compatible internal format for forward compatibility.
### What about ABDM / Ayushman Bharat integration?
The lab is in scope but not yet enrolled. ABDM's HRP/HFR registration is a 2026 roadmap item. The architecture supports it — our internal patient model already includes ABHA address fields, just not yet wired to the ABDM gateway.
### Why React Native and not native iOS + Android?
Cost and pace. One codebase ships in ~30% of the engineering time. The trade-off is that some platform-specific affordances (Apple HealthKit deep integration, for instance) are harder. We do not need them for this app. For a workout app or a fitness tracker we would think differently.
### How did you handle the OTP for older users on basic phones?
Pure SMS OTP with no auto-read dependency. The flow works on a Nokia 3310 (we tested). For users with smartphones, auto-read kicks in on Android via the SMS Retriever API. iOS handles it natively.
### What is the consent UX you settled on?
A two-screen consent on first launch. Screen 1: explicit purpose statements with toggles for "store my reports", "send me reminders", "use anonymised data for research" (default off). Screen 2: retention period (default 7 years per NABL), data export option (downloadable JSON + PDF zip), data deletion option (soft-delete first then hard-delete after 30 days). Every consent change is timestamped and signed.
### How did the older-patient cohort adopt the app?
Slowly at first. Branch staff demoed it at the counter on report-collection day. Adoption among the 50+ cohort hit 28% in month 3, 51% in month 9. The under-50 cohort hit 78% by month 6. We optimised for the older user — bigger fonts, fewer screens, single-tap key-results — which also pleased the younger ones.
### What was your team composition?
Two React Native engineers (one senior, one mid), one Python/Node backend engineer (HL7 + API), one designer at 0.5 FTE, our QA lead [Manvi](/team/manvi) at 0.4 FTE for the security and consent flows, and 0.2 FTE founder oversight from [Khushi](/team/khushi-kumari) on the UX side. Total: 4.1 FTE for 14 weeks.
### Where can I see your other healthcare work?
Our healthcare CRM build for [Fairway](/projects/fairway) (a medical company handling patient management and appointment tracking) shares the patient-record model. Our [Oasis Manors](/projects/oasis-manors) senior-care system has the most overlap on the SMS + family-alert pipeline.
## Related Reading
For DPDP-Act-grade healthcare apps, see TalkDrill (our in-house mobile product) for the same compliance pattern in a different domain
Need a Multi-Branch Healthcare or Diagnostics App?
We ship React Native apps with HL7 ingestion, FCM + SMS push, and DPDP-Act-compliant consent for Indian diagnostics chains in 12-16 weeks, fixed price. Typical project: ₹18-32 lakh. First call is technical, with the engineer who would lead your build. Suitable for 5+ branch labs with mature analyser fleets.