A complete engineering breakdown of the platform: every screen and capability across the Patient App, Doctor Portal, Ambulance Driver App and Admin/Ops Console — plus the dispatch, metered-pricing, verification, telemedicine, records and geo engines behind them. Architected around Bangladesh's regulatory reality, not around it.
This document is feature- and architecture-first. It maps the entire product surface — four applications, eight backend engines, the data model, the API layer, the payments topology and the reliability/scale foundations — so engineering, review and estimation all work from the same source of truth. Every design decision that is driven by Bangladeshi regulation is called out at the point it bites.
Each client app talks to a shared NestJS API over REST for actions and WebSocket for live state. Behind that API sit the engines that actually create value: dispatch, the metered fare, verification, telemedicine, records, geo/search, notifications and tourism. Cutting across all of them is a compliance layer that is not a feature — it is a constraint on every other feature.
Search, nearby, doctor & facility directory, lab price comparison, ambulance, video consult, checkup packages, records, tourism. Flutter · iOS + Android.
BMDC-verified onboarding, availability, video consult, e-prescription with the enforced drug matrix, patient records. Flutter + Web.
Onboarding, availability, job offers, navigation, trip flow, live meter, proof of trip. Flutter · Android-first.
Verification queue, live dispatch map, listings, pricing, finance, disputes, content, reports. Web.
Geospatial ambulance matching, offer cycle, timeout & re-assign, ops escalation.
Distance-based ambulance meter anchored to the government's Tk 35–40/km reference rate. The core IP.
BMDC registration + DGHS facility licence as a hard gate on every listing, with expiry and re-verification.
WebRTC consult rooms, consent capture, session recording metadata, e-prescription with the drug matrix hard-coded.
Patient-owned record vault, prescriptions, reports, Health ID / NID, NDHIE-ready export.
PostGIS radius + polygon queries, faceted objective search, no ranking signal.
Transactional-only push/SMS/in-app. Structurally incapable of promoting a doctor.
Multi-destination enquiry, itemised quote with disclosed fee, interpreter bundle, document workflow.
Standard marketplace software assumes it may rank supply, rate supply, promote supply and hold the money. In Bangladeshi healthcare, all four are prohibited or licensed. So this platform is built as a verified, neutral, price-transparent directory with a metered transaction layer — and the compliance layer is enforced in the schema and the API, not in a policy document that engineers can forget.
Those four numbers are the entire product thesis, and each one maps to a module in this document: transparency (§12 Search), diagnostics price comparison (§3 Patient App), the ambulance meter (§9 Pricing Engine), and verification (§7).
Every other spec you have seen for a health marketplace is illegal in Bangladesh in at least four ways. The BMDC Code of Professional Conduct, the BMDC Telemedicine Guidelines (July 2020) and the DGHS National Telehealth Guideline together remove star ratings, reviews, rankings, paid placement, promotional push, referral commission, offshore hosting and fund custody from the design space. This section states the constraints; the rest of the document obeys them.
These are not toggled off. They do not exist in the schema, the API or the UI.
The compliant product surface, in full.
A patient opening a doctor listing on any normal marketplace sees stars, review counts, "97% recommend", and a "Sponsored" badge. On Niramoy they see none of that, because BMDC Code §3 defines "practice promotion" to include publicity by "anybody acting on his behalf" — our marketing of a doctor is captured by the code. The card below is the complete permitted field set. Nothing else renders. The card component takes no rating, reviewCount or sponsored prop, because those columns do not exist.
Uniform typography — same size, not bold, not italic, per §3. No doctor's entry may be visually emphasised over another.
Default sort is distance for in-person and next available slot for video. Both are objective and non-comparative. There is no relevance score, no engagement signal, no bid.
The problem we exist to fix is the referral kickback. Diagnostic centres pay doctors 20–50% commission on tests they send over — pathology 50%, ELISA 40%, X-ray/ultrasound/histopathology 20%; flat fees of Tk 1,350 on an MRI, Tk 1,200 on a CT (New Age, 12 Aug 2022). The president of the Bangladesh Medical Association has publicly called it "a crime." If our software lets a doctor pick the lab, we have digitised the kickback.
So the architecture separates the two decisions and never lets them touch:
| Regulation | Source | What it forces in the build |
|---|---|---|
| No ratings, reviews, rankings, paid placement, promotional push | BMDC Code §3, §3.2b, §3.4.3, §3.5.4 | Neutral directory card; objective-only sort; Notification Hub restricted to transactional templates (§13) |
| No referral inducement; no fee-splitting | BMDC Code §4.3.1, §4.3.2 | Doctor↔lab decision separation (above); revenue model is patient-side fee + flat facility SaaS (§14) |
| Financial arrangements must be disclosed to all parties | BMDC Code §4.2.2 | A mandatory fee-disclosure block renders on every booking confirmation screen and every invoice (§14) |
| Must verify BMDC registration; must display reg. number | Telemedicine Guidelines §7.1, §7.2 | Verification Engine (§7) is a hard gate. bmdc_reg_no is NOT NULL on the doctor profile |
| AI may not counsel or prescribe | Telemedicine Guidelines §7.4 | AI features are assist-only, always labelled, never patient-facing as advice; no auto-generated prescriptions (§10) |
| Drug matrix by consult mode | Telemedicine Guidelines (e-prescription) | List O / A / B-1 / Prohibited enforced server-side in the prescription API. List A = video only. Narcotics never (§10) |
| Health data must sit inside Bangladesh | DGHS National Telehealth Guideline §5(6), §5(10) | In-country hosting; no Singapore/US region; media, DB, backups and video TURN/SFU all onshore (§19, §22) |
| Grievance mechanism required | Telemedicine Guidelines §7.5 | Dispute Centre in Admin console; in-app "Raise a complaint" on every consult and booking (§6) |
| Practice limited to Bangladeshi territory; overseas physicians need a BD licence | Telemedicine Guidelines §3.4; DGHS Telehealth §3.3.1g | Tourism module ships no foreign-doctor teleconsult at launch — enquiry + document workflow only (§13, §23) |
| Holding patient money and settling out = PSO licence | Draft PSO Regulation 2025 | Merchant-of-record / split-settlement via a licensed gateway. We never touch the funds (§14) |
| Third-party telehealth platforms need a licence; price list approved at licensing | DGHS National Telehealth Guideline | Price list is a single admin-managed, versioned, exportable artefact — so it can be filed and approved (§9) |
Every row above has a corresponding section in this document. If a developer is about to add a rating, a "recommended" badge, a promo push about a doctor, or a doctor payout on a lab booking, the schema should stop them before code review does.
The demand surface. Bilingual বাংলা/English, Android-first (72.4% of households own a smartphone, 80.8% urban — BBS ICT Household Survey, 2025/26). Designed for one urgent job (an ambulance, right now) and one repeat job (a test at a fair price, every few months).
Users are conditioned to expect stars. When they don't see them, the app must say why — a one-line explainer on the directory ("Bangladesh's medical council prohibits rating or ranking doctors. We show verified credentials and published fees instead.") turns a missing feature into a trust signal. This copy is part of the deliverable, not an afterthought.
The supply surface for the 134,568 physicians registered with BMDC (Nov 2024). Mobile app for consulting; web portal for schedule and records. Nothing here may be used to promote the doctor, and nothing here pays the doctor for a referral.
The supply surface for a market with 89.3% idle capacity (IJCCEM, 2022) and — as of 2021 — 4,821 registered ambulances in Dhaka out of 7,076 nationally (BRTA). We are not buying vehicles. We are giving the existing ones a dispatcher and a meter, both of which the market currently lacks entirely.
Ambulance syndicates control hospital gates and physically block outside vehicles. A newborn died in Shariatpur in August 2025 after a 40-minute blockade; a 70-year-old died in January 2026 after being held roughly an hour and a half; seven syndicate members were arrested at Rangpur Medical in June 2026. Software does not defeat this. The product response is: (a) gate-access agreements negotiated with partner hospitals before we route a single trip there, (b) a facility-level gate_access flag that determines whether we will dispatch to that hospital at all, and (c) the in-app incident report above, so the pattern is documented rather than absorbed silently by drivers.
In a regulated marketplace the console is not a back-office convenience — it is where the legal obligations are actually discharged. Verification, price integrity, grievance handling and the audit trail all live here, and all of them are manual by design because the registries have no APIs.
Roughly 95% of private facilities are operating on un-renewed licences: only 914 of 19,627 hospitals and clinics (4.66%) and 1,790 of 35,597 diagnostic centres (~5%) renewed (DGHS via The Daily Star, 2025). And around 36,000 of Bangladesh's 134,568 registered physicians — roughly one in four — practise without a renewed BMDC registration (Prothom Alo, 2024). Verification is not a checkbox in this market. It is the differentiator.
Telemedicine Guidelines §7.1 and §7.2 make this our legal obligation, not the doctor's.
A valid DGHS licence is a hard gate for listing. No licence, no listing, no exceptions.
BMDC's verification portal is a form-based lookup with no public API and no bulk registry. DGHS publishes facility lists as stale PDF dumps with no API. It would be technically trivial to scrape both and technically reckless to depend on either. An unauthorised scraper in the critical path of a legally-mandated verification obligation is a single ToS change, IP block or markup tweak away from silently failing — while we continue to display "Verified" to patients. So verification is a human workflow with stored evidence, expiry dates and scheduled re-verification. It is slower, it costs ops headcount, and it is the correct architecture. In parallel, we write to BMDC and DGHS requesting a formal data-sharing arrangement — that is the only legitimate path to automation.
Only PUBLISHED entities are returned by any public search, nearby or booking endpoint. The filter lives in the repository layer, not in each controller — so a new endpoint cannot accidentally leak an unverified provider. EXPIRED is reached automatically by a daily scheduler, never by a human forgetting.
| Entity | Evidence stored | Re-verification | Failure mode |
|---|---|---|---|
| Doctor | BMDC reg. no., portal lookup capture, certificate, NID, telemedicine-course confirmation | Before registration expiry; ad-hoc on complaint | Delisted; active bookings honoured then closed; patients notified |
| Hospital / Clinic | DGHS licence no. + expiry, renewal receipt, trade licence | Annual + on expiry date | Unpublished; ambulance dispatch to it continues (emergency), booking does not |
| Diagnostic centre | DGHS licence no. + expiry, renewal receipt, price list attestation | Annual + on expiry; price list every 90 days | Unpublished from comparison; existing bookings honoured |
| Ambulance / operator | BRTA registration, fitness, insurance, driver licence, equipment photos | On each document's expiry | Auto-offline; cannot receive offers |
| Tourism partner (abroad) | Accreditation, hospital licence in its own jurisdiction, signed agreement | Annual | Removed from destination browse |
Bangladesh's national emergency number, 999, owns no ambulances — it phones private operators, and averages 35–40 minutes to get a vehicle moving against a 15-minute clinical survival benchmark (BSS, 2025). There is no dedicated prehospital EMS in the country (TraumaLink / GHSP, 2022), no dispatch structure and no SOPs (Hossain et al., IJCCEM, 2022). This engine is the dispatch structure.
Candidates are filtered hard, then scored — clinical capability first, distance second.
Deterministic, tunable, and aggressive — because the clock is a survival clock.
Guarded transitions: PATIENT_ONBOARD requires the start-odometer photo; COMPLETED requires end-odometer + attendant confirmation. The meter starts at PATIENT_ONBOARD, not at ASSIGNED — the patient is not charged for the ambulance's approach. That single decision is a trust statement and it is hard-coded. Each transition emits a domain event consumed by the meter, notifications and the trip ledger.
No surge pricing. A logistics marketplace surges when demand spikes. An ambulance marketplace that raises the price when someone is dying is indefensible, and it would hand our entire brand argument to the syndicates we are displacing — they already charge 2–3× the government's Tk 35–40/km reference rate. The meter is fixed, published, and does not know what time it is or how many people are calling. Night and inter-district bands exist and are published in advance; they are not dynamic, and the multiplier is bounded and visible in the app before booking.
There is no meter, no universal rent chart, no monitoring authority and no national ambulance policy in Bangladesh — a draft was submitted in 2016 and never acted on (Financial Express, 2021). The government's own reference rate is Tk 35–40/km; syndicates charge 2–3× it. A Mymensingh→Dhaka trip that should cost Tk 7,000–8,000 is billed at Tk 8,000–15,000 (Prothom Alo, 2025). Building a published, deterministic, distance-based meter is the single most valuable thing this software does.
The per-km rate is anchored on the government's published Tk 35–40/km reference. We are not setting a price; we are enforcing the one that already exists on paper.
Same inputs → same fare, every time. The fare is a pure function of the rule version, the routed distance, the waiting time and the declared equipment. Nothing else.
Every fare stores its rule version, its GPS polyline, its distance derivation and its itemised components. A disputed fare can be reconstructed line by line, months later.
| Component | How it is calculated | Configurable | Rationale |
|---|---|---|---|
| Base fare | Flat start fee per ambulance type | Yes — per type, per city | Covers callout & approach; the approach distance itself is not billed |
| Distance | Per-km rate × routed distance, snapped to the road network from the GPS trace | Yes — banded | Anchored to the govt Tk 35–40/km reference rate. This is the heart of the meter |
| Distance bands | Optional taper on long inter-district trips (rate/km falls above X km) | Yes | Makes long transfers economic without gouging — the exact case syndicates exploit |
| Waiting | Free grace period, then per-minute | Yes | Hospital admission queues are long; the driver's time is real, but the grace protects the patient |
| Equipment surcharge | Additive: oxygen · ventilator · ICU kit · freezer | Yes — per item | Only applied if the vehicle's equipment was verified at onboarding. No verification, no surcharge |
| Attendant / paramedic | Additive, if the operator provides one and it is declared | Yes | Most vehicles carry no trained paramedic; where one exists it is a real, chargeable service |
| Night band | Fixed, published multiplier within a fixed time window | Yes — bounded & capped | Published in advance. Not dynamic. Not surge. Visible before the patient confirms |
| Return / one-way | Inter-district return leg policy, explicit | Yes | The single biggest source of opaque overcharging on long transfers |
| Toll / ferry pass-through | At cost, receipted | Yes — per corridor | Passed through at cost with no margin, and shown as such |
| Platform fee | Separately itemised patient-side service fee | Yes | Never hidden inside the fare. §4.2.2 disclosure obligation |
| Total | Sum of the above, itemised, shown live during the trip | — | The receipt the market has never had |
Computed from the routing engine's predicted distance and the active rule version. Shown as a range, with the per-km rate and every surcharge itemised before the patient confirms. Nobody in this market does this today.
Recomputed server-side from the actual GPS trace, throttled to a few updates a minute. Driver and patient see the identical number on their screens at the same moment. There is no version of the fare that only the driver can see.
Recomputed from the completed, road-snapped polyline. If it exceeds the top of the quoted range by more than a configurable tolerance, it is capped at the quoted maximum and the overage is flagged to ops for review — a route deviation is our problem to investigate, not the patient's to pay for.
Itemised receipt with the rule version, the distance, the map trace and each component. Stored immutably. Any dispute is resolved against this artefact, not against a driver's word.
A fare rule is never edited in place. Publishing a change creates a new version with an effective-from timestamp; every trip stores the fare_rule_version_id it was priced under. This gives us three things at once: correct historical reconstruction of any fare; a defensible answer to a dispute or a regulator; and a single exportable price-list artefact — which matters because the DGHS National Telehealth Guideline requires a provider to declare a price list at licensing, approved by the authority. The pricing manager exports exactly that document.
Diagnostic and consultation prices are not set by this engine. Those are declared by the facility and the doctor respectively, and we display them. We price only what we operate: the ambulance trip, and our own separately-itemised platform fee.
Paid video consultation is explicitly legal under the BMDC Telemedicine Guidelines (July 2020), §5.8.3.1. But §7 loads the platform — not the doctor — with a list of obligations, and §7.6 gives BMDC the power to blacklist a platform, after which no registered doctor may use it. That is an extinction event. This engine is built to make it impossible.
WebRTC, media served from inside Bangladesh.
Not a checkbox — a legal artefact.
"AI/ML may not counsel or prescribe." We take this literally.
This table is law, and it is implemented as a server-side guard on the prescription API. A doctor cannot bypass it by using a modified client, because the client never makes the decision.
| List | Permitted consult mode | When | Examples | Enforcement |
|---|---|---|---|---|
| List O | Any — video, audio or text | Any consult | OTC: paracetamol, ORS, antacids, antihistamines | Always allowed |
| List A | VIDEO ONLY | First consult or refill | Antifungals, eye drops, chronic refills (diabetes, hypertension, asthma) | API rejects the item if session.mode != VIDEO. The doctor sees why |
| List B-1 | Any | Follow-up only | Add-on medications | API rejects unless a prior consult with this doctor exists for this patient |
| Prohibited | NEVER | Never | Narcotics & psychotropics | Not in the formulary. Cannot be selected, cannot be free-texted past validation |
Additional hard rules baked into the prescription generator: drug names render in CAPITALS; the doctor's name, qualification and BMDC registration number appear on every prescription; transmission to a pharmacy requires explicit patient consent; and the patient retains free choice of pharmacy — which is precisely why we do not build exclusive pharmacy tie-ups, however commercially attractive they look.
IN_CONSULT is unreachable without CONSENT_GIVEN. PRESCRIBED is guarded by the drug matrix against the recorded session.mode. Nothing in the flow can be skipped by a client-side change.
A longitudinal record vault that outlives any single consult, facility or doctor — structured from day one to interoperate with the national health record exchange rather than to lock a patient into us.
The DGHS National Telehealth Guideline §5(6) requires health data to be "seated within the territorial jurisdiction of Bangladesh," and §5(10) prohibits overseas cloud hosting unless the provider has at least one data centre inside Bangladesh. So: the primary database, the object store holding every report and prescription, the backups, the video TURN/SFU relays and the log store are all in-country. Records are encrypted at rest with per-tenant keys; the object store is private with short-lived signed URLs; and no analytics pipeline exports raw PHI anywhere. See §19 and §22 for how this is actually deployed.
A search engine that must never learn what "best" means. Ranking is the default behaviour of every search system ever built, and here it is prohibited on doctors. That has to be an explicit architectural decision, or it will creep back in as "relevance."
Faceted and filtered — not scored.
PostGIS does the work.
BMDC Code §3.5.4 prohibits push, SMS or email promoting specific doctors. The safe way to comply is not a policy — it is to make the promotional message unsendable.
| Channel | Allowed content | Hard block |
|---|---|---|
| Push (FCM) | Booking confirmed · doctor is ready · ambulance assigned/arriving · report ready · prescription issued · payment receipt · document expiring | The broadcast composer has no field to attach a doctor. Doctor-scoped templates are transactional-only and require a matching booking ID |
| SMS | OTP · ambulance dispatched with vehicle & driver detail · appointment reminder · emergency fallback when the app is offline | No marketing SMS about any provider. Sender ID reserved for transactional routes |
| In-app inbox | Everything above, plus health-education content and policy updates | Health content may not name a doctor or facility as a recommendation |
| Receipts, invoices, records export, account security | No provider promotion | |
| Masked calling | Patient ⇄ driver, patient ⇄ facility, through a proxy number | Real numbers never exposed to either side |
Implementation: a template registry where every template is typed as TRANSACTIONAL or CONTENT. TRANSACTIONAL templates require a booking/trip/consult ID to render and cannot be sent to a segment. CONTENT templates can be broadcast but pass a compliance review gate and cannot reference a provider entity. There is no third type. Delivery runs on a queue with retries, dedup and per-user rate limits.
Bangladeshis spend US$4–5 billion a year on treatment abroad — more than the entire national health budget. That figure comes from Ahsan H Mansur, Governor of Bangladesh Bank (2025), alongside DCCI, on roughly 450,000–800,000 patient journeys a year. This is the only line in the platform with a ticket size that can carry a commission. It is also the one with the sharpest regulatory edge.
A "video-consult a foreign specialist before you travel" feature is the obvious product. It is also a regulatory problem: the DGHS National Telehealth Guideline (§3.3.1g) indicates that overseas physicians need a licence to practise in Bangladesh, and the BMDC Telemedicine Guidelines limit practice to Bangladeshi territory (§3.4). A cross-border teleconsult between an Indian specialist and a Dhaka patient, brokered by us, is not clearly lawful. Note also that Rhythm Group (BD) and Manipal Hospitals (India) announced exactly this in April 2026 — a medical-tourism deal that includes a digital video-consultation platform for pre-travel consults. Somebody is already shipping it. That is not a reason for us to; it is a reason to get a written legal opinion (§23) and let them find out first. Until we have that opinion, the tourism module ships enquiry, quotes, documents and logistics — not a consult room.
The sharpest monetisable insight in the research.
| Destination | What the data says | Product implication |
|---|---|---|
| India | ~50–60% of journeys. Cheapest, land border, no visa fee (Tk 1,500 processing). Bangladeshi medical arrivals: ~449,000 (2023) → 482,336 (2024) → 325,127 (2025). India reopened all visa categories to Bangladeshis on 28 June 2026, after a roughly two-year freeze, with an automated time-slot system across all five IVACs from 1 July 2026 | Do not build "India is closed" into the product. India is recovering fast and is the default destination. Visa-slot availability is a live data point worth surfacing |
| Thailand | ~65,000 BD patients/yr; 60% of all BD visa applications to Thailand are medical (~9,000/month). But ~80% of patients consider Thailand only after an Indian visa failure and abandon it on learning costs are 10–15× India's | The quote comparator must show the cost gap honestly and early, or we waste the patient's time and our own. Cardiac stent: India ~$2,000 vs Thailand $5,000–20,000 (Al Jazeera, Jan 2025) |
| China / Kunming | New, state-backed, ~1/4 of Thailand's cost, one-day green-channel visas, Bengali/English interpreters and halal food available | The interpreter bundle. The highest-margin, most differentiated offer we have |
| Malaysia | Record revenue from BD patients in 2025; 10,800+ BD health travellers to Feb 2026. MHTC ran Malaysia Healthcare Week in Dhaka on 8 April 2026 and its CEO publicly said they want partnerships with local healthcare facilitators | A government-backed warm lead. Business development, not engineering — but the module must support a formal partner integration when it lands |
Facilitator commissions in this industry typically run 10–15%, up to 30%, with quotes padded 25–35% — and the fee is baked invisibly into the patient's bundled quote. That opacity is the thing we disrupt: our fee is a separate, named line on the quote. Note that no verified Bangladesh-specific commission rate exists publicly — 10–15% is our working assumption for modelling, and it is labelled as an assumption everywhere it appears, including in the admin console.
This is the second architecture-rewriting constraint after advertising. The obvious design — patient pays us, we hold it, we settle out to the hospital minus our cut — puts us squarely in Payment System Operator territory. The draft PSO Regulation 2025 requires a Trust & Settlement Account, makes directors and the CEO personally liable for any shortfall, and carries a licence fee of Tk 5,00,000. Running a wallet is worse still — that is PSP/MFS licensing. So we do not do it.
Every one of these is a licensed activity, and the personal liability of the directors is the reason to take it seriously.
This entire topology depends on the chosen gateway actually supporting merchant-of-record-per-provider or split-settlement. If it does not, the architecture changes materially and the legal exposure changes with it. Get written confirmation from SSLCommerz / aamarPay / ShurjoPay before a line of payment code is written. This is a Phase 0 task, not a Phase 3 discovery. Indicative MDR for planning only (get written quotes): cards ~2.0–2.5%, MFS ~1.5–2.1%, setup Tk 4,000–25,000, settlement T+1 to T+3.
BMDC Code §4.2.2 is the one clause in the entire code that contemplates an intermediary like us — and what it demands is full financial disclosure to all parties. So disclosure is a UI component with a database-backed source of truth, rendered on every checkout screen and every invoice, in both languages. It states: what the provider charges, what we charge, who pays us, and what we do not receive.
| Line | Example | Who receives it |
|---|---|---|
| Consultation fee | Tk 800 | The doctor — in full, unreduced |
| Platform service fee | Tk 40 | Niramoy — for booking, records and support |
| Payment processing | Tk 16 | The licensed gateway |
| You pay | Tk 856 | — |
| We receive no commission from any doctor, hospital, laboratory or pharmacy for sending you to them. This sentence renders on the same screen. It is the brand. | ||
Cash remains a first-class path — for ambulance trips especially, where the patient may have no phone charge and no time. A cash trip is recorded against the operator, reconciled in the admin console, and our fee is invoiced to the operator monthly. Cash does not mean unmetered: the fare is still computed server-side and the receipt is still itemised.
Each is an explicit, guarded state machine emitting domain events. Nothing changes state by direct database write; every transition is a command with a precondition, and every transition emits an event consumed by notifications, the ledger and the audit log.
The gap between ORDER_ISSUED and FACILITY_CHOSEN is the most important gap in this system. The doctor is on one side of it and never crosses. Both events are written to decision_audit with actor and timestamp.
Event-sourced where it matters. The ambulance trip, the consultation and the lab order are event-sourced: the current state is a projection, and the event log is the truth. This is what makes a fare dispute, a prescription challenge or a regulatory audit answerable months later — we can replay exactly what happened, in order, with who did it. Appointments and tourism cases use a simpler state column with a transition log, because the audit stakes are lower.
The relational backbone. Spatial columns are GiST-indexed; clinical and financial tables are append-only; and the entities that regulation cares about carry their constraints in the schema, not in application code.
| Entity | Key fields | Notes & constraints |
|---|---|---|
| Patient | phone, name, sex, dob, blood_group, nid?, health_id? | OTP identity; family members via Dependant |
| Doctor | bmdc_reg_no (NOT NULL), bmdc_expiry, qualifications[], specialty, languages[], gender, fee_schedule | No rating, no review_count, no is_sponsored column exists. Compliance is enforced by absence |
| Facility | type, dghs_licence_no, licence_expiry, location geography(Point), services[], gate_access | Unpublished automatically on licence expiry. GiST index on location |
| Verification | subject_type, subject_id, status, evidence_uri, verified_by, verified_at, expires_at | Append-only. The legal artefact behind every "Verified" badge |
| Test (catalogue) | canonical_name, bn_name, synonyms[], category, sample_type | Ops-curated canonical catalogue; facility names map onto it |
| FacilityTestPrice | facility_id, test_id, price, declared_at, turnaround, home_collection | Facility-declared and timestamped. Stale prices are flagged; the price-integrity queue works this table |
| Package | facility_id, name, test_ids[], bundle_price | Bundle vs sum-of-parts shown honestly |
| InvestigationOrder | doctor_id, patient_id, test_ids[], indication | 🔴 Has NO facility_id column. Structurally cannot name a lab |
| LabBooking | patient_id, order_id?, facility_id, test_ids[], price_snapshot, state | 🔴 facility_id is set only by a patient action. No doctor payout links to this table |
| Appointment | doctor_id, patient_id, facility_id?, slot, state | In-person chamber booking |
| Consultation | doctor_id, patient_id, mode (VIDEO/AUDIO/TEXT), consent_id, started_at, ended_at | mode is what the drug matrix is enforced against. Immutable once closed |
| Prescription | consultation_id, items[], signed_pdf_uri, doctor_bmdc_no | Drug names CAPITALS; items validated against the drug matrix server-side |
| DrugFormulary | name, list_class (O / A / B1 / PROHIBITED), generic, strength | PROHIBITED rows are unselectable. The matrix is data, and it is versioned |
| Consent | patient_id, scope, text_version, granted_at, revoked_at | Append-only. Consent is never overwritten, only superseded |
| RecordItem | patient_id, type, source, file_uri, structured_payload (FHIR-aligned) | Encrypted at rest, in-country object store, signed short-lived URLs |
| RecordGrant | patient_id, doctor_id, scope, expires_at | Time-boxed, revocable. Every read against it is logged |
| Ambulance | operator_id, reg_no, type, capabilities[], equipment_evidence_uri, live_location | Capabilities are verified before they can attract a surcharge |
| AmbulanceTrip | patient_id, ambulance_id, state, pickup, destination, polyline, fare_id | Event-sourced. Polyline is the audit trail behind the fare |
| Fare | fare_rule_version_id, base, distance_km, distance_amt, waiting, equipment[], night_band, tolls, platform_fee, total | Itemised. Reconstructible. Never edited — corrections are new rows |
| FareRuleVersion | city, per_km_bands, base, surcharges, effective_from, published_by | Versioned & effective-dated. Exportable as the DGHS price-list declaration |
| PaymentIntent | gateway_ref, merchant_of_record, amount, provider_leg, platform_leg, status | Records what the gateway did. Holds no balance |
| PlatformInvoice | counterparty, period, lines[], vat, total | Our fee, invoiced separately. Never netted out of a doctor's fee |
| TourismCase | patient_id, destination, partner_id, quotes[], interpreter_booking_id?, state | Fee is a named line on every quote |
| Interpreter | destination, languages[], rate, vetted_at | The Kunming bundle as a first-class entity |
| Grievance | subject_type, subject_id, category, sla_due, resolution | Mandatory under Telemedicine Guidelines §7.5 |
| decision_audit | actor_type, actor_id, action, subject, payload, at | 🔴 Append-only. Proves the doctor never chose the lab |
| audit_log | actor, action, entity, before, after, ip, at | Every privileged action. Append-only, tamper-evident |
| Translation | locale, key, value | বাংলা / English copy editable without a release |
Note the three rows marked 🔴. Between them they encode the two hardest legal constraints in the entire system — the absence of a rating column, the absence of a facility column on the doctor's order, and the append-only proof that the two decisions stayed apart. A developer cannot violate BMDC §4.3.1 through this schema without a migration, and a migration gets reviewed.
Adapter pattern throughout. Payments, SMS, maps, video and push each sit behind a clean interface. The core booking/dispatch/pricing logic calls the interface, never a vendor. This matters more here than in a normal build: if the chosen gateway turns out not to support split-settlement (§14), or the video vendor cannot serve media from inside Bangladesh (§11), we swap the adapter — we do not rewrite the platform.
Bangladesh's Personal Data Protection Act was passed by Parliament on 10 April 2026 (deemed effective from 6 November 2025), and the Cyber Security Ordinance 2025 (gazetted 21 May 2025) replaced the Cyber Security Act 2023. Combined with the DGHS residency rules, the security model is not a checklist item — it is a licensing condition.
Horizontally scaled behind a load balancer; shared state in Redis and Postgres, never in the process. Adding capacity is adding a container.
PostgreSQL primary + read replica. GiST indexes on all geography columns. High-volume tables (location pings, audit) partitioned by day.
Live ambulance positions in Redis GEO for hot lookups, persisted to Postgres/PostGIS for the audit trail. Throttled ingestion keeps writes bounded as the fleet grows.
Redis for the test catalogue, facility prices, fare rules and — critically — routing results. Map API calls are the single biggest variable cost in the system and are cached hard.
BullMQ queues for notifications, PDF generation, OCR, re-verification schedules and reconciliation. Nothing slow ever blocks a request — least of all a dispatch request.
The SFU scales independently of the API. Consult concurrency is the metric to watch; it is the only component whose cost grows with minutes rather than requests.
Service areas are polygons; fare rules and supply are scoped to a city. Launching Chattogram is configuration and supply onboarding, not a rebuild.
This is not a ride-hailing fleet. Ambulance concurrency in Dhaka is measured in dozens, not thousands. We engineer for correctness and auditability first, and for throughput second — honestly.
Android-first, low-end device targets, aggressive payload trimming, offline-tolerant record vault. 4G coverage is national, but device quality is not uniform.
| Layer | Technology | Why this, here |
|---|---|---|
| Mobile (3 apps) | Flutter (Dart) | One codebase → iOS + Android across Patient, Doctor and Driver apps. That is the single biggest cost lever in an 18–22 week build with a small team. Strong on low-end Android, which is the actual device base |
| Web (Admin/Ops, Doctor portal) | Next.js + TypeScript | Shares types with the API; server-rendered admin is fast on poor connections |
| Backend | NestJS (Node, TypeScript), modular | One language across API, web and workers — a small team cannot afford two ecosystems. Strong module boundaries map cleanly onto our eight engines. First-class WebSocket support for the live meter and dispatch. (Laravel is a defensible alternative if the delivery team's depth is PHP — the architecture does not depend on the choice.) |
| Database | PostgreSQL 16 + PostGIS | Non-negotiable. Nearby, service-area polygons, ambulance matching and route traces are all geospatial. PostGIS does this natively with GiST indexes; MySQL does not do it properly. Postgres also gives us partitioning, JSONB for FHIR-aligned payloads, and full-text search — so no separate search cluster in v1 |
| Cache / live state | Redis (+ Redis GEO) | Hot driver positions, offer locks, fare-rule cache, routing cache, pub/sub backplane for WebSocket fan-out across API instances |
| Queue | BullMQ on Redis | Notifications, PDFs, OCR, re-verification schedules, reconciliation. Retries and dead-letter handling out of the box |
| Real-time | WebSocket (Socket.IO / native) + Redis pub/sub | Live meter, trip tracking, dispatch offers, consult signalling |
| Video | LiveKit (self-hosted WebRTC SFU + TURN) | Chosen specifically because it can be self-hosted inside Bangladesh. A managed SaaS whose media relays sit in Singapore fails DGHS §5(10). Agora remains a pluggable fallback only if it can demonstrably serve media from a BD point of presence |
| Maps | MapLibre + vector tiles; routing behind a provider interface | MapLibre avoids per-view licensing on a high-traffic map surface. Routing/distance-matrix stays behind an interface so Google Maps can be swapped in where accuracy justifies the cost |
| Payments | SSLCommerz / aamarPay / ShurjoPay | Licensed BD gateways covering bKash, Nagad, Rocket and cards. Chosen on split-settlement support (§14) — that capability, confirmed in writing, is the selection criterion |
| Push / SMS | FCM + local BD SMS gateway | Notifications and OTP. SMS is the fallback when the app cannot reach a patient in an emergency |
| Object storage | S3-compatible, hosted in Bangladesh | Reports, prescriptions, verification evidence, proof-of-trip photos. Encrypted, private, signed short-lived URLs |
| Hosting | In-country BD datacentre / BD cloud region | 🔴 Mandatory. DGHS §5(10) prohibits overseas cloud unless the provider has a BD data centre. We do not propose a Singapore or US region. Provider selection is a Phase 0 task with hard requirements: BD DC, managed Postgres or competent DBA support, and an SLA |
| Ops | Docker, CI/CD, self-hosted Sentry, uptime monitoring | Reproducible deploys; observability that does not export PHI offshore |
Not a preference. A requirement.
The stack decision that most teams get wrong.
Iterative delivery in two-week sprints, each ending with a working demo on staging. The one thing that is not negotiable is Phase 0: legal opinion and supply-side validation happen before a line of production code, because both can invalidate the architecture.
2-week cycles: plan → build → demo → feedback. Scope stays flexible, direction stays yours.
Each phase ends with a reviewable deliverable and a go/no-go checkpoint.
Pricing math, state transitions and the drug matrix ship with tests. These are the parts where a bug is a legal event.
Progress, staging link, blockers, next-sprint plan — in writing.
| Phase | Weeks | Deliverable | Exit criteria |
|---|---|---|---|
| 0 · Pre-code 🔴 | 1–2 | Written legal opinion from a Bangladeshi lawyer on the §23 risk register. Written confirmation of gateway split-settlement. ~20 supply-side validation calls to hospitals, diagnostic centres and ambulance operators. Hosting provider selected (BD DC). Final scope, screen list, API contract | Legal opinion in hand. Gateway capability confirmed in writing. Supply-side willingness to list — validated or the model changes. Signed-off spec & data model |
| 1 · Foundation | 3–5 | UI/UX (bilingual), DB + PostGIS schema, auth, base API, Verification Engine + admin verification queue, in-country infra | A doctor and a facility can be verified end-to-end on staging, with stored evidence |
| 2 · MVP: trust wedge + volume engine | 6–12 | Patient App (search, nearby, directory, lab price comparison, checkup packages) · Ambulance (driver app, dispatch engine, metered pricing, proof of trip) · Admin/Ops (dispatch console, listings, pricing manager) · payments via gateway | A real ambulance trip, dispatched, metered, paid and receipted, on staging. A real lab booking with a price comparison and a disclosed fee |
| 3 · Telemedicine & records | 13–18 | Doctor App · video consult (in-country SFU) · consent capture · e-prescription with the drug matrix enforced · health records vault · grievance centre · NDHIE-ready export | A video consult produces a compliant, signed e-prescription. A List A drug is refused on an audio session. Records land in the vault |
| 4 · Tourism & international | 19–20 | Medical tourism module (multi-destination, itemised quotes, interpreter bundle, document workflow), international search | A tourism case runs enquiry → quote → document workflow, with our fee as a visible line |
| 5 · Hardening & launch | 21–22 | Load test on the real-time paths, security review, compliance walkthrough against §2, store submission, ops training, handover | Live on both stores. Ops team trained on the verification queue — because that is the job that never stops |
Three findings in Phase 0 could each change the architecture: (1) a lawyer confirming that a facility-side technology fee is prohibited would force the revenue model onto flat SaaS alone; (2) a gateway that cannot do split-settlement would force a different payments topology; (3) hospital chains refusing to list at all — which no public source confirms they would accept — would change what we are even building. It costs two weeks. Skipping it risks the whole budget.
Fare math, state transitions, the drug matrix, the publication filter. Property-based tests on the meter.
Gateway callbacks (idempotent), routing, video signalling, notification templates.
Automated assertions: no rating field is ever serialised; a List A drug on an audio session is rejected; an unverified provider never appears in any response.
Real ambulance operators and a real doctor test on staging before launch. Ops runs the verification queue for two weeks pre-launch.
Reproducible environments, the accounts you will need, and a clean handover with full source-code ownership.
| Service | Purpose | Owner |
|---|---|---|
| Hosting — BD datacentre / BD cloud region | App, DB, Redis, object storage, video SFU, backups | Client billing, we set up. Must be in-country |
| Payment gateway (SSLCommerz / aamarPay / ShurjoPay) | bKash, Nagad, Rocket, cards — with split-settlement | Client merchant account, we integrate. Confirm split-settlement in writing first |
| Apple Developer + Google Play | Publish three apps | Client accounts, we submit |
| Maps / routing | Tiles, directions, distance matrix, ETA | Client billing, we integrate |
| SMS gateway (BD) | OTP, ambulance dispatch alerts | Client account, we integrate |
| Firebase | Push notifications (tokens only, no PHI) | Client project, we configure |
| Domain + SSL | Web & API endpoints | Client, we configure |
| Company & compliance | RJSC registration, trade licence, e-TIN, VAT + BIN, bank account, UBID (Digital Commerce Guidelines 2021) | Client, with a lawyer. Not an engineering task — but a launch blocker |
| Telehealth platform licence | DGHS — assume an independently-operating app requires one, with a price list declared and approved at licensing | Client, with a lawyer. See §23 |
We set up and configure every service; the accounts stay in your name, so ownership and billing are always yours. The two rows in bold at the bottom are not software tasks — they are the reason Phase 0 exists.
Every item below is a genuine unknown, not a hedge. Each one has been researched to the limit of what public sources can answer, and each one hits a wall that only a qualified Bangladeshi lawyer — and in two cases a call to DGHS — can get past. They are listed here rather than buried, because a spec that pretends these are settled is a spec that will need rewriting after launch. Phase 0 exists to close them.
| # | Open question | Why it is unresolved | What it changes if the answer is bad | Owner |
|---|---|---|---|---|
| R1 | Is a facility-side technology fee lawful? BMDC §4.3.1 bans a doctor accepting inducement for referral; §4.3.2 bans fee-splitting. §4.2.2 is the only clause contemplating an intermediary, and it demands full disclosure. Is a disclosed, patient-initiated, facility-side fee inside or outside that line? | It is professional misconduct, not (yet) a crime, and no High Court ruling has been found. The clause was not written with platforms in mind | The revenue model. If prohibited, we fall back to patient-side fee + flat, non-volume-tied facility SaaS only. The architecture already supports this — but the business case narrows | Lawyer |
| R2 | Can a commercial app lawfully publish a doctor directory at all? BMDC Code §3.4.7 says directories should be "published by professional medical organizations" | A commercial listing app arguably is not one. Many operate anyway — Doctorola, DocTime, Praava. Tolerated ≠ lawful. Unresolved | The doctor directory itself. Worst case: the directory becomes doctor-consented-only, or is dropped in favour of facility-led listings | Lawyer |
| R3 | Does an independently-operating telehealth app need a DGHS licence, and is the licensing window open? The DGHS National Telehealth Guideline states third-party systems, apps, webs and platforms need to be licensed, and that a provider must declare a price list at licensing, approved by the authority (§12.4) | Could not confirm the guideline is gazetted, or that the licensing process is operational. Documents dated Feb & May 2026 | Launch timing. We assume a licence is required and build the exportable price-list artefact (§9) accordingly. A closed licensing window could delay launch | Lawyer + a call to DGHS |
| R4 | Can a BD patient lawfully video-consult a foreign physician through our platform? DGHS Telehealth §3.3.1g indicates overseas physicians need a BD licence; BMDC Telemedicine §3.4 limits practice to Bangladeshi territory | Directly contradicts the obvious tourism feature. Rhythm × Manipal announced exactly this in April 2026 — either they have a view we do not, or they have exposure they have not priced | The tourism module's headline feature. We ship without it (§13). If lawful, it is a fast follow-on; if not, we have avoided the exposure | Lawyer |
| R5 | Does the chosen gateway actually support split-settlement / merchant-of-record per provider? | Vendor documentation is not conclusive. Must be confirmed in writing | The entire payments topology (§14). Without it we either hold funds — which needs a PSO licence, Tk 5,00,000, directors personally liable — or we redesign. Non-negotiable Phase 0 item | Client + gateway, in writing |
| R6 | Does an ambulance aggregator need a licence? | No licence for an ambulance aggregator could be found. There is no national ambulance policy, no monitoring authority, and no meter. That is the opportunity — and the ambiguity | The ambulance module's legal footing. Silence in the law is not the same as permission | Lawyer |
| R7 | Will the drafted Health Protection Act criminalise referral commissions — and would it capture us? | An Act is being drafted and may criminalise the practice | Nothing, if we build correctly. Our model takes no commission and splits the decisions structurally (§2), so a statutory ban should strengthen our position. This risk is listed so that stays true | Lawyer (monitor) |
| R8 | What exactly does the Personal Data Protection Act (passed 10 April 2026, deemed effective 6 Nov 2025) require of a health-data controller? | The Act is very new; implementation rules and the regulator's posture are not yet established | Consent flows, retention, breach-notification timelines, DPO obligations. We build to the strictest reasonable reading and adjust | Lawyer |
| R9 | Will hospitals and diagnostic centres actually list, and pay? | 🔴 NO public source confirms hospital-chain willingness to accept a third-party referral platform. Chains with their own apps (Square, Labaid, Evercare, Ibn Sina) have little incentive to pay for patients who would walk in anyway. The ones most likely to sign are mid-tier centres with idle capacity | Everything. This is a commercial risk, not a legal one — but it is the single biggest assumption in the plan. ~20 primary validation calls in Phase 0, before code | Client + us, Phase 0 |
| R10 | Can we get a formal BMDC / DGHS data-sharing arrangement for verification? | Neither has a public API. BMDC is a form-based lookup; DGHS publishes stale PDFs | Ops cost. Without it, verification stays manual forever — which is our design assumption anyway (§7), so this is upside, not a blocker | Client (write to BMDC/DGHS) |
R5 and R9 are build-blocking — they must be answered before Phase 1 starts, because they can invalidate the payments architecture and the business model respectively. R1, R2, R3, R4, R6 and R8 are launch-blocking — they need a written opinion before the app is public, but the build can proceed against the conservative reading, which is what this specification encodes throughout. R7 and R10 are monitor-only. The conservative reading is already the design. That is the point of building it this way: if every one of these questions comes back with the worst plausible answer, the platform in this document still stands.
Launch is the start. In this domain there is a permanent operational obligation — verification expires, licences lapse, prices go stale — and someone must own it every single day.
| Job | Cadence | Why it cannot be automated away |
|---|---|---|
| Verification queue | Daily | No BMDC or DGHS API exists. Every doctor and facility is verified by a human against the registry, with stored evidence |
| Expiry & re-verification | Daily (system-flagged, human-actioned) | Registrations and licences lapse. ~1 in 4 doctors practise without renewed registration; ~95% of facilities on un-renewed licences. Our badge means nothing if it is stale |
| Price integrity | Weekly + on report | Facility-declared prices drift. Price accuracy is the product; a wrong price is a broken promise |
| Grievance handling | Continuous, SLA-bound | Mandated by Telemedicine Guidelines §7.5 |
| Content moderation | On submission | A doctor writing "Best cardiologist in Dhaka" in their bio is a BMDC violation by us |
| Manual dispatch fallback | Continuous | A large share of this market still phones. The console must let a human dispatch a call-in patient |
The last tag is not a joke. It is the one roadmap item that must survive every future product manager, every growth experiment and every investor who asks why there are no stars. Write it into the codebase, the compliance playbook and the ops training — because the schema will hold the line only as long as someone remembers why it was built that way.