01
System overview
One Django application serves three kinds of caller: staff browsers inside the hospital, patients on tokenised links, and other systems over the interoperability API. Underneath it sit two very different engines — deterministic clinical rules that never leave the server, and an optional language model used only for drafting.
02
Deployment options
The same build runs in all three. The decision is about where the record lives and whether any text may leave the premises.
| Option | Where the record lives | Drafting | Suits |
|---|---|---|---|
| Cloud | Managed database in your cloud account or ours, one region | Provider of your choice, or off | Most hospitals; fastest to stand up |
| On-premises | Your data centre, your database | Off, or a model you host | Hospitals whose policy forbids PHI leaving the site |
| Hybrid | Record on-premises; only the application tier in cloud | Off by default | Groups with a central IT function and local constraints |
"May any patient text leave the hospital?" If the answer is no, set the provider to offline and every clinical rule, score, check and alert still runs. What you lose is drafting: notes, summaries and letters are then assembled from templates rather than written.
03
Reference cloud topology
A worked example on AWS in the Mumbai region. Adapt names to your standards; nothing here is required by the application.
- Edge: CloudFront for static assets and documents, in front of an S3 bucket. TLS terminated at an Application Load Balancer for the application itself.
- Application: two or more instances behind the load balancer across availability zones, running Gunicorn or mod_wsgi. Stateless — sessions live in the database, so an instance can be replaced at any time.
- Database: RDS MySQL or PostgreSQL, Multi-AZ, automated backups plus point-in-time recovery, encrypted with KMS.
- Objects: S3 for uploads and collected static files, with versioning on and public access blocked; the application signs URLs.
- Secrets: Secrets Manager or Parameter Store, injected as environment variables at boot. No key ever lives in source or in an image.
- Access: no SSH from the internet; Session Manager for shell access; a private subnet for the database with no public route.
- Monitoring: CloudWatch logs and alarms, plus the application's own health endpoint.
04
Tenancy and data isolation
HealthTeky is multi-tenant by hospital. Every clinical row carries a hospital, middleware resolves the current hospital from the signed-in user's membership, and queries are scoped to it. A user with no membership sees nothing.
This is row-level isolation in a shared schema, not a database per hospital. It is enforced in application code and covered by tests, including one that asserts another hospital's patient is unreachable through the API. If your policy requires physical separation, deploy a dedicated instance and database per hospital — the application supports that with no code change, at the cost of running more infrastructure.
Machine callers are scoped differently and more strictly: an API token belongs to exactly one hospital, and the hospital is taken from the token rather than from anything in the request.
05
Identity, roles and access
- Staff sign in to the application; each has a membership with a role (owner, admin, manager, doctor, nurse, pharmacist, lab technician, receptionist, billing, counsellor, viewer).
- Permissions are derived from the role, not assigned per user, so a ward's access pattern is readable at a glance. The Guardian consults them for every consequential action — preparing a prescription, signing a note, approving an order.
- Patients receive unguessable tokenised links with an expiry. No account, no password. A link grants access to exactly one intake, recovery plan or care page.
- Machines authenticate with a hospital API token (
Authorization: Bearer), never a session cookie, with an optional IP allowlist per client. Only a SHA-256 hash of each token is stored; the token itself is shown once at creation. - Break-glass access is recorded as such, and every instance is reviewed by name at the governance meeting.
SAML or OIDC against [Azure AD / Google Workspace / Keycloak] is a standard integration and is scoped per hospital during implementation. Until it is in place, enforce your password policy and multi-factor requirements at the identity layer you already run.
06
The AI layer
Two categories, and the difference matters more than any other line in this document.
| Category | What it does | Network | Behaviour if the model is off |
|---|---|---|---|
| Deterministic engines | Red flags, NEWS2, sepsis screening, medication safety, lab trends, pharmacy checks, critical-result detection, pre-op risk, screening recalls, consent rules, FHIR and HL7 | None — pure Python in-process | Unaffected |
| Generative drafting | Consultation notes, discharge summaries, radiology report structure, referral letters, Ask-the-Record answers | Calls the configured provider | Falls back to template-assembled text, marked as such |
How the gateway behaves
- Provider choice is configuration: Anthropic Claude, OpenAI, Groq, or
offline. Keys come from the environment only. - Failure is not an outage. A rate limit, timeout or refusal falls back to the offline implementation and the audit entry records the reason.
- Patient data is never an instruction. Record and transcript content is enclosed in tags and the model is told to ignore instructions inside it; uploaded protocols are screened for injected text before indexing.
- Answers are grounding-checked. Statements that cannot be traced to the record are flagged rather than displayed as fact.
- Every generation is audited with the provider, the model, the prompt version and any fallback reason.
07
Interoperability
- FHIR R4, read:
/ai/connect/fhir/serves Patient, Condition, AllergyIntolerance, MedicationStatement, Observation, Encounter and DiagnosticReport, plusPatient/<id>/$everythingand a CapabilityStatement. Vitals and common labs carry LOINC codes; anything unmapped uses our own code system rather than inventing a LOINC code. - HL7 v2, inbound:
/ai/connect/hl7/accepts ORU results and ADT messages and replies with a proper ACK. Results are matched to a patient by UHID, then by phone and surname; a message that matches nobody is logged, never used to create a patient. - ABDM: ABHA number (Verhoeff) and address validation, and consent artefacts carrying purpose, health-information types and expiry. Gateway registration is a deployment step for the hospital as the participating facility.
- Disclosure requires consent. A read through the API is refused unless a live consent artefact covers it, and the refusal is audited.
- Every message is logged in both directions with its type, sender, outcome and what was applied.
FHIR is read-only. Write-back into your HIS is scoped per hospital, because the first thing an integration can do wrong is overwrite a record it did not author. DICOM images are not ingested; radiology support works on the radiologist's text.
08
Security
- In transit: TLS everywhere, HSTS at the edge. The interoperability API refuses session cookies, so a browser cannot be tricked into making a call on a staff member's behalf.
- At rest: database and object storage encryption through your cloud's key management, or full-disk encryption on-premises.
- Uploaded patient files are never public. When object storage is enabled, media URLs are signed and expire; static assets are served either signed or through a CDN. Verify any deployment with
python manage.py check_s3, which reports exactly what is reachable and what is refused. - Secrets: environment variables only, sourced from your secret store. The repository carries a
.env.examplewith no values. - Application: Django's CSRF protection on all state-changing forms, session cookies marked secure and HTTP-only in production, and per-session rate limits on public endpoints.
- AI-specific: prompt-injection screening on ingested documents, grounding checks on generated text, and a kill switch per model.
- Audit: hash-chained and append-only. Verification reports exactly where a chain breaks — most often after a database restore, which is worth knowing before an assessor asks.
- Key rotation: rotate provider and API tokens on staff change and on any suspected exposure. Disabling an API client takes effect on the next request.
09
Availability and recovery
| Objective | Reference target | How it is met |
|---|---|---|
| Recovery point (RPO) | [5 minutes] | Point-in-time recovery on the managed database |
| Recovery time (RTO) | [2 hours] | Multi-AZ failover; application instances are stateless and replaceable |
| Backup retention | [35 days] | Automated snapshots plus a monthly retained copy |
| Restore drill | [Twice a year] | Restore to a scratch environment and verify the audit chain afterwards |
Clinical work must continue when the platform does not. Each module has a manual fallback recorded during implementation — the paper or existing-HIS process that staff revert to — and the go-live rehearsal exercises it once, deliberately.
10
Sizing and performance
Load is driven by concurrent staff sessions and inbound messages rather than by bed count, but beds are the easier number to plan from.
| Hospital | Application | Database | Notes |
|---|---|---|---|
| Up to 100 beds | [2 × 2 vCPU / 4 GB] | [2 vCPU / 8 GB] | Single region, Multi-AZ database |
| 100–400 beds | [2–4 × 4 vCPU / 8 GB] | [4 vCPU / 16 GB] | Add a read replica for reporting |
| 400+ beds or a group | [Auto-scaling group] | [8 vCPU / 32 GB + replica] | Separate the interoperability endpoint onto its own instances |
Drafting calls are synchronous today: a scribe draft holds its request until the provider replies, typically a few seconds. Agents run inside the request that triggered them rather than on a queue. A background worker (Celery or RQ) is the next infrastructure step for hospitals at the top of the table, and it changes deployment, not clinical behaviour.
11
Observability
Ordinary application monitoring, plus four signals that are specific to running clinical AI. Alert on all four.
| Signal | Why it matters | Suggested alert |
|---|---|---|
| Provider fallback rate | Drafting silently degraded to templates | [> 20% of calls in an hour] |
| Clinician override rate | A model disagreeing with clinicians more than it did | [Sustained rise over two review cycles] |
| Critical results unacknowledged | The safety net is not closing | [Any result past its deadline] |
| Rejected interop messages | A feed changed format or broke | [> 5 rejections in an hour] |
12
Environments and release
- Environments: development, staging with de-identified data, and production. Staging mirrors production configuration, including the provider setting.
- Database changes ship as Django migrations, applied as a deployment step. Migrations are never generated on a production server.
- The safety suite — missed stroke, negation, non-English symptoms, allergy blocks, kill switch, prompt injection, fabricated citations — runs in the pipeline and blocks a release when a scenario fails.
- Rollback is a redeploy of the previous build. Because migrations are additive, a rollback does not require a database restore in the ordinary case.
- Change windows are agreed with the hospital; clinical-facing changes are announced to the wards affected before they land.
13
Known limitations
Stated plainly, so nobody discovers them during an incident.
- FHIR is read-only. No write-back to your HIS yet.
- No image interpretation. DICOM is not read; radiology support works on dictated text.
- Row-level tenancy in a shared schema, unless you deploy a dedicated instance per hospital.
- No background queue yet. Drafting and agents run in-request.
- Patient links have no second factor. They are unguessable and expiring, but anyone holding a link can open that patient's page. An OTP to the registered phone is available as an option and is worth enabling before wide use.
- Language coverage for patient-facing flows is English, Hindi and Kannada.
- The seed formulary ships as a starting point; an unknown drug is flagged rather than cleared until your formulary is loaded.
14
IT readiness checklist
Cloud, on-premises or hybrid — and the provider decision that goes with it.
Staging with de-identified data, production, and access paths for both.
With named owners and a rotation schedule.
TLS certificate, hostname, and the redirect from the old entry point if there is one.
Including verification of the audit chain after the restore.
Which analyser, HIS or PACS sends what, over which protocol, from which IP.
SSO now, or local accounts with your MFA policy applied at the identity layer.
Including the four AI-specific signals and who receives them out of hours.
The manual fallback per module, agreed with the clinical leads.