Case study
Building a Multi-Tenant Care-Coordination Platform for Hospitals
Turned a largely manual patient-coordination process into an automated, multi-tenant system connected to each hospital's EHR.
- Project
- Healthcare care-coordination platform
- Industry
- Healthcare SaaS (orthopedic & surgical care)
- Role
- Backend engineer → owner of core subsystems
- Duration
- ~3 years
- Node.js
- Express
- MongoDB / Mongoose
- Redis
- Bull / BullMQ
- Auth0
- FHIR / HL7
- Twilio
- LLM / RAG
- React
- Mocha / Chai / Sinon
- Testcontainers
The context
A healthcare technology company (confidential) building a multi-tenant SaaS platform for orthopedic and surgical practices. The platform connects hospital EHR systems, patient communication channels (SMS, voice, in-app), and clinical staff workflows across a patient's whole surgical journey, from scheduling through post-op recovery.
The problem
Before the automation layer existed, coordinating a surgical journey was largely manual. Staff tracked appointments and sent pre-op instructions, consent requests, post-op check-ins, and outcome surveys by hand. There was no consistent way to trigger the right communication to the right patient at the right time, and no reliable link between the hospital's EHR data and what the platform needed to automate.
Each hospital also ran a different EHR vendor with its own data formats, timezones, and event semantics. Nothing could be built once and reused safely across hospitals, and every new integration risked leaking data across tenants or misreading a hospital's local time.
My responsibility
- Owned design and implementation of the patient journey automation engine: a state machine that schedules and sends communications based on appointment events, consent status, and quiet-hours rules
- Built and maintained the EHR integration layer, normalizing clinical events from multiple vendors into a common FHIR-based model
- Designed multi-tenant data access patterns so every query, background job, and cache key is scoped to the correct hospital
- Integrated LLM features (patient chat, triage assistance, clinical note drafting), with safeguards for opted-out patients and LLM outages
- Built the Bull/BullMQ + Redis job infrastructure behind scheduled and event-driven patient outreach
- Contributed to the patient-reported outcomes analytics pipeline and campaign systems, enforcing consent, quiet hours, and opt-outs as platform-wide policy
Architecture
- Frontend (web / mobile)
- Tenant filter → Controllers → Domain services
- Background jobsBull/BullMQ + RedisPatient messaging (SMS / voice / in-app)
- EHR integration layerFHIR/HL7 adapter per vendorClinical event normalization
- LLM serviceChat / triage / notesGuarded by consent + tenant checks
MongoDB (tenant-scoped, per hospital)
Key decisions
Tenant scoping as a structural rule, not a convention
Every query, job payload, and cache key carries a hospital identifier, checked at the data-access layer rather than trusted from the caller.
FHIR as the common internal model
Clinical events from every vendor are normalized to FHIR, so a new EHR vendor needs one adapter instead of changes to every downstream consumer.
Patient communication outside the request cycle
Messages go out through background jobs, so a slow or failed send never blocks a clinical workflow and can be retried safely.
LLM service behind its own API boundary
AI features can be added, disabled, or rolled back per hospital without touching core backend logic.
Technical challenges
1.Multi-vendor EHR interoperability
Vendors returned the same logical event (an appointment scheduled or rescheduled) in different shapes, timezones, and semantics. A normalization layer with explicit per-site timezone handling ensures appointment times are always read in the hospital's local time. Left unfixed, that bug class silently contacts patients at the wrong time or about the wrong procedure.
2.Journey automation under real-world messiness
Patients reschedule, cancel, get readmitted, or revoke consent mid-journey, and EHR events don't always arrive in order. Consent and quiet hours became universal gates evaluated once, centrally, instead of being duplicated per message type, so one fix closes the gap for every channel.
3.Safe background-job scaling across tenants
Bursts of EHR events and campaigns had to be processed without cross-tenant leakage or duplicate sends. Idempotent jobs on tenant-partitioned Redis queues mean a retry or burst from one hospital can never affect another's patients or double-send a message.
4.Introducing LLM features safely in a regulated context
AI chat and triage had edge cases with patient-safety consequences, such as an opted-out patient getting an AI reply or a clinical note drafted without human review. The fix was an explicit consent check ahead of every LLM call and defined fallback behavior when the LLM service is degraded or unavailable.
Results
- Automated a previously fully manual patient-coordination workflow across [N] hospital tenants / [N] patients
- Reduced manual staff outreach effort by an estimated [X]%
- Processed [N] appointment/EHR events per month through the integration layer, across [N] EHR vendors
- Eliminated a class of timezone and data-mismatch errors that previously caused patients to be contacted at the wrong time
- AI chat/triage resolved [X]% of patient inquiries without staff intervention, with zero opted-out patients receiving AI replies after the fix
What I learned
- Treat multi-tenancy and consent/compliance as structural properties of the system, not something each feature re-checks.
- Drive root-cause fixes across a whole subsystem by tracing a reported symptom back to the shared code path all callers go through.
- Know when AI is safe to introduce into a regulated clinical workflow and when a human needs to stay in the loop.
- Balance moving quickly in a fast product against the higher cost of getting patient-safety-adjacent logic wrong.