Discovery & requirements
Patient journey mapping (call-and-paper baseline), legacy-system protocol survey, multi-city tenancy model, US and EU healthcare-privacy review (GDPR, CCPA, HIPAA-capable scaffolding).
Case study · HealthTech · Diagnostics
How we shipped a production diagnostics patient platform — native iOS and Android apps, a web personal cabinet, and the adapter glue into legacy scheduling and accounting systems — built on Symfony with reliable push pipelines on APNs and FCM, a 2,500-item test catalog, and a privacy posture aligned with GDPR for the European Union and CCPA for the United States from day one.
Unilab's administrative staff were manually handling appointment requests, inbound calls, patient data entry, and emailing test results across a network operating in more than forty cities. The existing scheduling and accounting backends were workhorses, but they had been built years before mobile traffic was a serious load class and did not expose any customer-facing surface a patient could reach from a phone. The lab needed a unified patient platform — registration and personal cabinet, online appointment booking, digital results, a searchable catalog of 2,500-plus tests, an interactive map of offices, and push reminders — that integrated with the existing scheduling and accounting systems instead of replacing them. The platform also had to hold up under healthcare privacy expectations in the United States and the European Union: GDPR for European patients, CCPA for California patients, HIPAA-capable architecture for any future US-launch scenarios. We built the platform as a Symfony backend with adapter services into the legacy systems, paired with native iOS (Swift) and Android (Kotlin) patient clients and a React web personal cabinet. The result is a production diagnostics platform that scales across cities, removes the manual administrative tax, and is positioned for compliant operation across the US and EU.
A snapshot of what the Unilab build delivered across iOS, Android, web, and a Symfony backend wired into legacy scheduling and accounting systems.

The platform decision dominates the reliability story of a healthcare patient app. We chose native Swift (iOS) and Kotlin (Android) over a Flutter MVP and over a WordPress patient-portal plugin because the trade-offs line up cleanly with what a multi-city lab actually needs. WordPress portals are appealing on a sales call but fall over fast under the load profile of a lab — appointment-window mutations, accounting reconciliations, push delivery at result-ready time — and pin the operator to a plugin ecosystem that no healthcare auditor takes seriously. Flutter is excellent for forms-heavy apps but adds a bridge between Dart and the platform push pipelines and biometric APIs that result-ready notifications cannot afford to be noisy about.
The build leans on Apple Push Notification service on iOS, Firebase Cloud Messaging on Android, and the Symfony framework on the backend — proven primitives that give us deterministic push behavior, predictable background sync semantics, and a backend layer that healthcare operators in the US and EU recognize and trust.
| Dimension | Native iOS + Android (Unilab) | Flutter | WordPress portal |
|---|---|---|---|
| Push reliability | Direct APNs / FCM; deterministic delivery | Bridge to platform pipelines; rare race conditions | Web push only; weak on iOS |
| Scheduling adapter fit | Clean REST surface from Symfony adapter | Same backend reachable; identical fit | Plugin-bound; rigid mapping |
| Multi-city scaling | Tenanted data model; configuration-only city add | Same; UI parity strong | Network of sites or multi-site WP — operationally heavy |
| Accounting integration latency | Adapter service caches reads; sub-second UI | Same backend; identical latency | Synchronous plugin calls; user-visible waits |
| Biometric & Face ID | Native LocalAuthentication / BiometricPrompt | Plugin bridge; usually fine | Not available outside native wrapper |
| App Store review fit | First-class — healthcare entitlements clean | First-class; same review path | Often rejected as "web wrapper" |
| Audit posture (US + EU) | Operator-owned event store, immutable | Identical backend guarantees | Plugin DB; weak audit story |
References: Apple Push Notification service documentation, Firebase Cloud Messaging guide, Symfony framework documentation.

The iOS client is built in Swift with SwiftUI for the UI layer and a clean MVVM split that keeps the appointment booking flow readable for the next engineer who has to touch it. The booking flow is the spine of the patient experience: a patient opens the app, browses tests, picks a date, time, and office, and confirms — with the adapter service translating the request into the legacy scheduling system's protocol behind the scenes. The interactive office map is a separate flow with a MapKit-backed view and city-aware filtering, so a patient living in one city does not have to wade through offices in another to find a walk-in slot.
Push notifications are wired through APNs and segmented by intent — appointment reminders, result-ready notifications, and promotional pushes each live in their own category so users can manage them independently. Background fetch keeps the personal cabinet warm so a patient who opens the app at 7 AM sees today's appointment without waiting on a network round-trip. The end-to-end iOS surface is delivered as part of our mobile app development practice, with shared design tokens between iOS and Android so the patient experience reads as one product across both stores.

The Android client is written in Kotlin with Jetpack Compose for the UI and a foreground service for result-ready delivery on Samsung, Xiaomi, OnePlus, and Pixel device families, where aggressive battery optimizers terminate background services without warning. Results land as encrypted blobs over an HTTPS pull triggered by the FCM push, never inside the push payload itself, and a BiometricPrompt step gates access so a phone left on a café table does not surface a patient's blood panel to a stranger. WorkManager handles non-urgent operations — catalog updates, office-map refreshes, telemetry flush — with backoff semantics that respect Doze mode across Android 10 through Android 14.
The 2,500-item test catalog is where the Android client earns its keep. Structured search across categories, sub-categories, and free-text terms is served by a Symfony-backed search index, with city-aware availability so a patient in one city never sees a test that's not offered there. Per-test details include preparation instructions, turnaround times, and pricing — the same fields the legacy accounting system already maintains, exposed through the accounting adapter so the source of truth remains the operator's accounting database. The same engineering team carries iOS and Android in lockstep as part of our iOS and Android engineering practice.

The scheduling and accounting adapters carry the integration weight of the platform. Each is a dedicated Symfony module that sits between the patient clients and the corresponding legacy system, translating mobile-shaped requests into the native protocol of the legacy backend and absorbing back-pressure when the legacy system is slow. The scheduling adapter manages connection pooling, caches non-mutating reads in Redis, and writes an audit trail of every appointment mutation so the operator can reconstruct activity per regulator request. The accounting adapter does the equivalent for pricing and invoice data, keeping the accounting database as the single source of truth and exposing a clean REST surface to the mobile clients without exposing the legacy system to the public internet.
Patient data lives behind role-based access control and is encrypted at rest with key rotation. The posture is built to align with GDPR obligations for patients in the European Union and CCPA / CPRA obligations for patients in California and the broader United States, with a HIPAA-capable architecture ready to scaffold a Business Associate Agreement when a US-launch scenario calls for one. Every result delivery, every appointment mutation, and every accounting reconciliation writes to an immutable audit log that survives the next regulator audit as a documentation exercise rather than an archaeological dig.
Compliance posture: GDPR-aligned · ISO 27001 ready · SOC 2 Type II in progress · HIPAA-capable · CCPA-acknowledged.
A five-phase build that took Unilab from operator pain points to production across iOS, Android, web, and the integration adapters.
Patient journey mapping (call-and-paper baseline), legacy-system protocol survey, multi-city tenancy model, US and EU healthcare-privacy review (GDPR, CCPA, HIPAA-capable scaffolding).
Symfony backend skeleton, scheduling-system adapter spec, accounting-system adapter spec, REST surface for mobile clients, immutable audit-log schema, role-based access control.
Native Swift / SwiftUI iOS client, native Kotlin / Jetpack Compose Android client, React web personal cabinet, 2,500-item catalog with structured search, MapKit office finder.
Push pipelines on APNs and FCM, encrypted result delivery with biometric gating, audit-log testing, role-permission review, multi-city load test at projected patient volume.
App Store + Google Play submission across US and EU storefronts, per-city rollout choreography, on-call runbooks for the adapter services, post-launch reconciliation with accounting.
Unilab's accounting backend was the workhorse of the existing operation, and the patient platform was built to amplify it rather than replace it. The accounting adapter sits between the patient clients and the accounting database, translating mobile requests into the accounting system's native protocol while writing every transaction to an immutable reconciliation log. Pricing for the 2,500-item catalog is owned by the accounting system; the adapter caches reads in Redis with a short TTL so the patient app shows fresh prices without hammering the legacy database. Invoice generation runs on the accounting side; the adapter only exposes a read-only view so a patient can pull a receipt without ever touching the operator's bookkeeping records. The subsystem was built with operator handoff in mind: a clinic administrator opens the operator console, sees the day's appointments per city, and can intervene — reschedule, refund, contact patient — without ever leaving the platform. Cross-city operators can scope their view by region, which is how a single administrator covers operations in multiple cities during quiet shifts without losing the per-city audit trail.
The Unilab platform was architected for healthcare operators serving patients across the United States and the European Union. The English-language build serves patients in California, New York, Texas, Florida, and Washington in the US, and patients in the Netherlands, Germany, France, Ireland, and Sweden in the EU, without a separate codebase per region. Consent flows are region-aware at the client layer: patients in the EU and EEA receive a GDPR-style granular consent screen with separate toggles for result-delivery channels and optional product analytics; patients in California receive a CCPA-style "Do Not Sell or Share My Personal Information" disclosure in the same flow. Data-handling practices are aligned with GDPR for European patients and with the US state-privacy patchwork — CCPA / CPRA (California), VCDPA (Virginia), CPA (Colorado), CTDPA (Connecticut), UCPA (Utah), TDPSA (Texas), and Oregon CPA. The HIPAA-capable architecture provides scaffolding for a Business Associate Agreement scenario, even though HIPAA applies only when the operator is a covered entity under US law.
Backend deployment runs across EU and US regions in parallel — Netherlands, Germany, France, Sweden, and Ireland for EU coverage; US East and US West for North America — with Symfony services and PostgreSQL instances provisioned identically through Terraform. The patient-data store and the audit log can be pinned to either US or EU regions for future data-residency commitments, and the adapter services are stateless so they can be scaled independently per region. Both the App Store age rating and the Google Play content rating were calibrated for a healthcare app, and the in-app privacy policy was drafted to document exactly the architecture above, citing GDPR obligations and California CCPA obligations directly. The engineering team behind the build runs a CET workday with East-Coast US overlap (9 AM–1 PM ET) for stand-ups, store-review choreography, and on-call response.
The active custom software development roadmap for Unilab includes a telehealth video-consultation tier, deeper integration with the operator's accounting system for direct insurance-claim handoff, a per-physician portal for partner clinics, and a structured-results JSON-LD layer so patient results render cleanly in third-party health records. A B2B tier with bring-your-own-domain, team management, and SSO is planned for US and EU corporate-health programs. Infrastructure plans include further per-city sharding, an internal continuous-verification harness for the audit-log invariants, and a future independent readiness assessment scaffolded into the cloud & DevOps roadmap.
If you are planning a diagnostics patient platform, a multi-city healthcare app, or any mobile product where the integration story with legacy scheduling and accounting backends has to hold up under a regulator review for audiences in the US and EU, we have shipped this stack end-to-end and can compress the build timeline meaningfully. The live iOS client is available at the Apple App Store on iOS and Android, and the engineering team behind it sits inside YuSMP Group. We work fixed-price for well-scoped MVPs and on dedicated development teams for ongoing delivery, with a CET workday and a guaranteed East-Coast US overlap (9 AM–1 PM ET) window for stand-ups, demos, and incident response.
A focused MVP covering native iOS and Android patient clients, a web personal cabinet, appointment booking, digital test results, and a scheduling-system adapter typically costs $160k–$320k. Adding a 2,500-item test catalog with structured search, an interactive office map, push notifications, accounting-system integration, multi-city support, and audit-ready healthcare logging brings a full platform to $360k–$700k. The dominant cost drivers are the legacy scheduling-system adapter, the accounting integration, and the platform-specific push pipelines on Apple Push Notification service and Firebase Cloud Messaging.
Healthcare patient apps depend on platform-specific push reliability, background fetch behavior, and biometric-authentication primitives that mature faster on native than on Flutter wrappers. Native Kotlin and Swift expose APNs and FCM, Face ID and biometric prompts, and background URL-session and WorkManager primitives directly, so appointment reminders, result-ready notifications, and silent refreshes land predictably across Samsung, Xiaomi, OnePlus, Pixel, and iPhone. Flutter is excellent for forms-heavy apps but adds a bridge between Dart and platform push and biometric layers that healthcare apps cannot afford to be noisy about.
Most lab scheduling systems are not internet-facing and were not designed for mobile traffic. The integration sits behind a dedicated adapter service — a Symfony module that translates patient-app requests into the scheduling system's native protocol, manages connection pooling, and absorbs back-pressure when the legacy system is slow. The adapter caches non-mutating reads in Redis, exposes a clean REST surface to the mobile clients, and writes an audit trail of every appointment mutation so the operator can reconstruct activity across US and EU compliance audits.
Multi-city scaling is a data-model problem before it is an infrastructure problem. Offices, scheduling windows, test menus, and pricing all live as first-class tenants of the platform — each city is configurable independently, and the patient app reads only the catalog and the office map relevant to the user's location. The backend runs stateless workers behind a city-aware router, so adding a new city is a configuration change against the tenant store rather than a code release, and Symfony's caching layer prevents catalog reads from hot-spotting any single database.
A focused MVP with native iOS and Android clients, a web personal cabinet, appointment booking, digital results, and a scheduling-system adapter typically takes 14–22 weeks. Adding a 2,500-item test catalog, an interactive office map, push pipelines, accounting integration, and multi-city tenancy adds 8–14 weeks. The legacy-adapter work is frequently underestimated and should be budgeted at 4–6 weeks of dedicated effort, because scheduling-system protocols vary by lab network and rarely match the patient-app data model on the first pass.
Related cases
Cross-platform diet and meal-planning app — Flutter, calorie engine, grocery ordering, US & EU compliant subscription tier.
View case → Sports Media · MobileCross-platform sports news app and web portal — Telegram-bot CMS, Markdown pipeline, native iOS + Android.
View case → Retail · FashionRetail consultant app for boutique inventory across stores — ElasticSearch search, 1C integration, multi-store reach.
View case →