Softechinfra
Development

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, median report time cut from 36 hours to 6.

K
Khushi Singh
July 16, 202514 min read
We Built a Mobile App for a 9-Branch Pathology Lab: Reports in 6 Hours, Not 36

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.

9
Branches Across Tamil Nadu
~28K
Active Patients in Year 1
6 hr
New Median Report Delivery (was 36 hr)

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.

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 come with heavy yearly 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 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 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:

    MSH|^~\&|XN550|LAB1|MIRTH|HOSP|20250716093412||ORU^R01|MSG00001|P|2.5
      PID|1||MR-44218^^^LAB^MR||SUNDARAMURTHY^RAGHAVAN||19580322|M
      OBR|1|||CBC^Complete Blood Count|||20250716092400
      OBX|1|NM|HGB^Haemoglobin||13.4|g/dL|13.0-17.0|N|||F
      OBX|2|NM|WBC^White Cell Count||7.2|10^3/uL|4.0-11.0|N|||F

    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 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:

    Report delivery timeline (median, hours) BEFORE — paper + email + WhatsApp loop Sample to lab — 1.5 h Analyser run + verify — 2 h Email + branch print + call patient — 5 h Patient travels to branch / waits for WhatsApp scan — 27.5 h Total median: 36 hours AFTER — direct push to patient mobile Sample to lab — 1.5 h Analyser run + verify — 2 h, then push (median 2.5 h to open) Total median: 6 hours

    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

    ComponentNotes
    Hetzner CCX23 (app + Postgres)Right-sized for 1,840 daily reports
    Hetzner CX22 (Mirth Connect)HL7 bridge box, isolated from app
    Backup S3 (Cloudflare R2)14 GB hot + 90-day retention
    Firebase FCMFree tier covers our volume
    Gupshup SMS fallback~9,000 SMS/month for stale tokens
    Apple Developer ProgramAnnual fee amortised
    Google Play ConsoleOne-time fee amortised over 12 months
    Sentry (errors)Team plan
    Engineering retainer (0.4 FTE)Covers app updates + Mirth changes
    Compliance + DPO retainerExternal DPO advisory hours

    A Note on the TalkDrill Mobile Parallels

    We carried two patterns directly from our work on TalkDrill, 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.

    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.

    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 at 0.4 FTE for the security and consent flows, and 0.2 FTE founder oversight from Khushi 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 (a medical company handling patient management and appointment tracking) shares the patient-record model. Our Oasis Manors senior-care system has the most overlap on the SMS + family-alert pipeline.

    If you found this useful

    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. First call is technical, with the engineer who would lead your build. Suitable for 5+ branch labs with mature analyser fleets.

    Book a Mobile-App Scoping Call

    Tags:
    Mobile AppReact NativePathologyHL7HealthcareDPDP ActCase StudyIndian SMB
    Share this post:
    K

    Khushi Singh

    UI/UX Designer at Softechinfra focused on crafting intuitive, user-friendly digital experiences.