The right blood type isn't enough: it has to be someone who can get there
A donor register that matches each request on blood-group compatibility and on whether the donor can actually reach the hospital. One platform serves a web admin and a mobile client from the same records.
Who, what, and how long
Healthcare & Dental Practices
16 weeks
Fixed price, phased
Client name withheld under NDA. Engagement details are shown to the extent our agreement permits.
The hard problem
- 01
A donor register is only useful in the hours after a request. Matching on blood group alone produces a list mostly made of people two hundred miles away, and coordinators end up phoning down it by hand until they find someone close enough to matter.
Addresses were free text, which made geographic matching impossible, not merely imprecise: there was nothing to query against. So group compatibility was the only available filter, and it produces a list ordered by nothing useful. The cost was paid in the worst hour, by a coordinator working a phone list while a hospital waited.
Matching on compatibility and geography together, over a real three-level area hierarchy, so the first names a coordinator sees are the ones who can be at the hospital today. The same records serve the admin and the mobile client through parallel web and API controllers.
How the pieces fit
- 01
Modeled the area hierarchy properly: division, district, sub-district
Location is modeled as a true hierarchy of division, district and sub-district, so searches can widen gradually.
- 02
Made matching compatibility crossed with reachability, never either alone
Matching crosses compatibility with geography in one query, so the list is ordered by who can realistically attend.
- 03
Served admin and mobile from one application with parallel web and API controllers
Serving both from one application was chosen over a separate API service because two clients disagreeing about a donor's state is the failure that matters here.
- 04
Recorded donation history so someone who gave three weeks ago isn't asked again
Donation history suppresses anyone inside their recovery window automatically, and the suppression is visible on the donor's own profile.
- 05
Let organizations hold their own request queues without forking the register
Organization queues were added after the register worked, so the model was proven on one coordinator's workflow before it had to serve several.
The system we were asked to build
The organization keeps a register of volunteer donors and connects them to urgent requests. We built the register, the matching, and the one application that serves both the coordinators' admin and the donors' phones.
A volunteer donor register whose value exists entirely in the hours after an urgent request. Coordinators were matching on blood group, getting a list mostly composed of people two hundred miles away, and phoning down it by hand until they found someone close enough to matter. The engagement covered the register, the matching and the two clients that read it.
Backend & Platform Engineering
Compatible and reachable
Matching crosses blood-group compatibility with a real area hierarchy, so the top of the list can actually attend.
Matching crosses blood-group compatibility with geography in one query, because a compatible donor four hours away isn't a match for a hospital that needs someone this afternoon. The result is ordered by who can realistically attend, which is the only ordering a coordinator can act on.
- Compatibility and geography resolved in one query
- Ordered by who can actually attend today
- Never group-filtered, then distance-sorted as an afterthought
The list a coordinator actually rings for an O negative request in Savar, ordered by travel time: two donors grayed out by the 90-day rule, eight callable, and 118 more too far to matter.
Eight divisions down to 495 sub-districts: Kishoreganj's 1,204 donors split across seven sub-districts, only 54 of them O negative and three sub-districts holding none.
Three-level geography
Division, district and sub-district stored as records, with no free-text address field.
Division, district and sub-district are records with real relationships, so a search can widen a step at a time (this sub-district, then the district, then the division) instead of jumping from nothing to everything. Donors select from the hierarchy at registration, which is what makes the data clean enough to match on at all.
- Three geographic levels as records, not free text
- Searches widen one level at a time
- Selected at registration, so the data stays matchable
One application, two clients
Parallel web and API controllers over the same records, so admin and phone never disagree.
Web controllers and API controllers sit side by side over the same models and the same authorization rules, so the admin and the mobile client can't disagree about a donor's state. Sanctum handles the API tokens; the shared layer beneath means a rule added for one client is enforced for the other by construction, with no second implementation to drift.
- Parallel web and API controllers over identical models
- Shared authorization, so the two clients can't diverge
- A rule added once is enforced for both
The same request on the donor's phone: it reaches a donor 2.4 km away, the group matches, and the register already knows he became eligible on 14 Sep.
One donor's whole record: seven donations, the 90-day gap drawn as a bar he has cleared, and the one request he couldn't attend left in place, not tidied away.
History that protects donors
Anyone inside their recovery window is suppressed automatically. Over-asking is how registers lose people.
A donor inside their recovery window is suppressed from results automatically, with no warning left for someone to miss. Over-asking is how registers lose people (a donor contacted three weeks after donating stops answering), so the register protects them from the coordinator by default. The suppression is visible in the donor's own profile, so nobody wonders why they stopped hearing from it.
- Recovery-window donors suppressed automatically, not flagged
- Protects donors from over-asking by default
- Suppression visible on the donor's own profile
Organizations with their own queues
Eleven hospitals, clinics and drives holding 41 open requests against one shared register, each with its own queue and none able to see another's donors.
Hospitals and drives hold their own requests without the register being forked per organization.
Hospitals and blood drives hold their own request queues inside the one register, with their own staff and their own history, so an organization gets what it needs without the register being forked per organization. Requests are records the register can report on across all of them, which makes national supply visible without an aggregation exercise.
- Per-organization request queues within one register
- No fork per hospital or drive
- Cross-organization reporting comes for free
Phase by phase
Phase 1: The Register
Who, What Type, And Where
Built the donor record on a real area hierarchy in place of a free-text address, because everything downstream depends on knowing where someone actually is.
- Donor Register
- Area Hierarchy
- Blood Group Model
Phase 2: Matching
Compatible And Reachable
Made the match a cross of group compatibility and area, so the list a coordinator opens is ordered by who can help today, not by who is theoretically suitable.
- Compatibility Rules
- Area Matching
- Ranked Results
Phase 3: Two Clients, One Application
Web And API Side By Side
Built parallel web and API controllers over the same records, so the coordinators' admin and the donors' phones never disagree about a request's state.
- Web Admin
- Mobile API
- Token Auth
Phase 4: Not Asking Twice
History That Protects Donors
Recorded donation history and used it to suppress requests to anyone inside their recovery window, because a register that over-asks is a register people leave.
- Donation History
- Eligibility Window
- Contact Suppression
A resting donor's own profile: 75 of 90 days since her last donation, no requests until 2 Oct, and the reason shown to her, so she never has to guess.
What it carries now
Group + area
Matching inputs
3
Area levels modelled
2
Clients from one codebase
0
Donors contacted while ineligible
Matching inputs, area levels and clients are descriptions of the system. Donors contacted while ineligible is zero by construction: anyone inside their recovery window is excluded from results instead of being shown with a warning someone might overlook.
Client name withheld under NDA. Figures are approximate, drawn from the engagement’s own reporting.
What the architecture settled
A match nobody can attend isn't a match. Reachability belongs in the query, not in the phone call afterward.
A compatible donor who can't attend today isn't a match, and putting reachability in the query, instead of the phone call afterward, is the whole difference.
Free-text addresses make geographic matching impossible, and the cost is paid in the worst hour.
Free-text addresses don't make geographic matching hard; they make it impossible, and the bill arrives in the hour when the register matters most.
Parallel web and API controllers over one set of records is what stops two clients disagreeing.
One set of records behind two clients is what stops a coordinator and a donor seeing different states, which is the failure a second implementation guarantees eventually.
A register that over-asks its donors quietly shrinks, so eligibility windows are a retention feature.
Suppression protects the register itself: donors contacted too soon stop answering, and a shrinking register fails silently long before anyone notices.
How the work was run
The area hierarchy went in before the matching did, because free-text addresses make the whole question unanswerable and everything else depended on fixing that first. Web and API controllers were built in the same pass so the two clients could never drift apart.
Phased with the area hierarchy built and populated before any matching work, since matching on geography requires geography to exist as data. Donation history and the recovery-window suppression were built in the same phase as matching, because a register that over-asks its donors is one that quietly shrinks.
One request, narrowed
From 12,486 names to the 8 who can be at the hospital today
An O negative request at a hospital in Savar, taken apart into the stages the matching query resolves together: the blood group, the area hierarchy, the 90-day window, and travel time. Each stage shows who left the list and why. Switch tabs, or use the arrow keys once one is focused.
O−Savar Community Medical Centre · needed today, 3:00 pm
Candidates left
- Registered12,486
- O negative612
- Dhaka division·
- Dhaka district·
- Past 90 days·
- Callable now·
12,486612match the requested group
The request is for O negative, so the register starts from the donors whose group matches it. Every other group leaves the list before geography is even considered.
- 612kept: O negative, across all eight divisions
- −11,874left the list: a different blood group
One query, not four passes. Compatibility, area and the 90-day window are resolved together, which is why 0 donors have been contacted while ineligible. The 60-minute reach is illustrative, set on this request.
From a request in one queue to a list both clients agree on
One Laravel application instead of a separate API service, because two clients disagreeing about a donor’s state is the failure that matters here. A rule added for one client is enforced for the other by construction.
- 01 · TriggerRequest raised in a queueA hospital, clinic or drive raises it in its own queue inside the one register, so no organization needs a fork of the register.
- 02 · IngestionParallel web and API controllersBlade web controllers and REST API controllers with Sanctum tokens sit side by side over the same models and the same authorization rules.
- 03 · EngineOne matching queryGroup compatibility and the area hierarchy are resolved together, ordered by who can attend, with anyone inside the 90-day window excluded outright.
- 04 · StateThe register in MySQLDivision, district and sub-district are related records; donation history sits on each donor; requests are records reportable across every organization.
- 05 · DeliveryCoordinator console and donor phoneBoth clients read the same records, so the admin and the phone can't disagree about a donor's or a request's state.
What the register won't do
Donor safety, privacy & a register that stays true
Nobody inside 90 days can be called
Donation history is recorded, and anyone inside their 90-day window is excluded from results automatically, with no warning for a coordinator to miss. Donors contacted while ineligible: zero, by construction. The suppression is visible on the donor's own profile.
One register, walled queues
Hospitals, clinics and drives each hold their own requests, staff and history inside the one register, and none can see another's donors. Web and API controllers share one authorization layer, so the rule holds identically on the console and the phone.
Places are records, not free text
Donors choose their division, district and sub-district from the hierarchy at registration, so matching queries real places. The console and the phone read one set of records, so a request's state can't differ between them.
Running a register that has to answer in the worst hour? Scope your build in 3 minutes.
Scope your buildNearby engagements
Web PlatformsThe ransomware attack that became a four-hour non-event
A ransomware attack encrypted the primary patient records server. Drilled offsite backups and a written runbook turned what could have been a scramble into a full restore inside the recovery time objective.
Healthcare & Dental Practices · Ongoing retainer
E-commerceA cart that won't check out until the prescription is real
An online pharmacy where a prescription is a first-class record with its own lifecycle, and prescription-only items simply can't leave the cart without one.
Healthcare & Dental Practices · 20 weeks
Web PlatformsA medicine isn't a SKU, so the catalog is generic, strength and company before it's a product
A pharmacy counter system whose catalog is modeled on how medicines actually differ (generic, strength and manufacturer as separate axes), so when a brand is out of stock the counter can find an equivalent instead of turning the customer away.
Healthcare & Dental Practices · 16 weeks
Let's talk
Running a large platform, shaping a first MVP, or getting a product ready for a funding round? Tell us where you are. We'll shape the process around it, and stay with you after launch.














