Building a Multi-Tenant Lab Information System: Architecture Decisions We'd Make Again
A multi-tenant lab information system lets one platform serve multiple labs or branches while keeping each tenant's patient data isolated. Here's how we built one, and what actually held up under real usage.

A multi-tenant lab information system lets a single software platform serve multiple diagnostic labs, or multiple branches of the same lab network, while keeping each tenant's patient data properly isolated. We built one for City Care Lab, a diagnostics network in Pakistan, replacing a manual, phone-and-spreadsheet workflow with a unified platform for staff scheduling, report handling, and patient tracking.
These are the architecture decisions that held up under real usage, and a couple we'd reconsider on a second build.
The Core Problem: One Codebase, Isolated Data
Health diagnostics data carries a different risk profile than most business software. A bug that leaks one tenant's data into another tenant's view isn't a minor incident. It's a compliance and trust failure, full stop.
At the same time, running a fully separate application instance per branch or per lab partner gets expensive to maintain fast, and it makes the cross-tenant reporting City Care Lab needed for network-wide operations much harder to pull off. The architecture had to isolate data cleanly without duplicating the entire application per tenant.
Decision 1: Row-Level Tenant Isolation, Not Separate Databases
We chose a shared database with a tenant identifier on every row, enforced at the query layer, over spinning up a separate database per branch. Separate databases per tenant sound safer at first glance, but they push complexity into deployment and migrations. Every schema change has to run N times instead of once, and cross-branch reporting means querying N databases and merging results in application code.
Row-level isolation, enforced consistently through the ORM layer and covered by tests that specifically check for cross-tenant leakage, gave us the same isolation guarantee without that operational overhead. This is the decision we'd make again without hesitation.
Decision 2: Real-Time Report Status With Firebase
Lab staff needed to see report status change live: sample received, in processing, ready for review, without refreshing a page or polling an API on a timer. We used Firebase for this specific real-time layer on top of a MySQL system of record, rather than trying to make the primary relational database handle real-time push updates itself.
That split, MySQL as the durable source of truth, Firebase as the live status layer, cut patient report delivery time by 60% just by removing the lag between a report being ready and staff actually knowing it was ready.
Decision 3: Role-Based Access Control From Day One
Because report data is sensitive, we built role-based access control and audit logging into the data layer from the initial schema design, not as a feature bolted on after launch. Front-desk staff, lab technicians, and administrators each see a different slice of the same data, and every access to a patient record gets logged.
The common mistake I see with healthcare software is retrofitting access control after a system is already live. It touches nearly every query in the application, and doing it early instead of late saved us a lot of pain later.
Decision 4: Automating the Boring, High-Error Parts
Beyond the core lab workflow, we automated staff scheduling, previously coordinated by phone, and introduced an online booking system so patients could book appointments without calling in. Neither of these is glamorous engineering work.
But they were the source of most of the platform's measurable impact: a 70% reduction in scheduling errors and a 60% reduction in appointment booking time, simply by replacing manual coordination with a system that physically couldn't double-book a slot.
What We'd Do Differently Next Time
In hindsight, we'd introduce automated cross-tenant isolation tests earlier in the build, rather than mid-project. On a system where a data leak is a serious incident, that test suite should exist before the first tenant's real data ever touches the system, not after.
We'd also formalize the tenant-scoping pattern into a shared internal library sooner. We ended up refactoring several early queries to use it consistently partway through the build, which is exactly the kind of rework a good discovery phase helps you avoid.
The Results
- Cut patient report delivery time by 60% with automation
- Streamlined staff scheduling, reducing manual errors by 70%
- Reduced appointment booking time by 60% with an online system
- Improved lab report accuracy and turnaround time by 40%
- Increased patient engagement through managed social media, contributing to a 20% rise in new patients
If you're building healthcare, diagnostics, or any other software that has to isolate sensitive data across multiple tenants, this is exactly the kind of architecture problem our web development team scopes out before writing a line of code.
Have a project like this?
Tell us about it and we'll get back to you within one business day.