Clinic records app scaling
Clinic records app scaling and launch checklist
A clinic records app stays fast by paginating every list, indexing the main questions, and deferring heavy work until a measured trigger fires. At launch, apply 6 rules, watch 10 signals and hold the performance targets below.
Last checked
Rules to apply at launch
- Pagination: Patient lists, timelines and access-log views use keyset pagination on (created_at, id) behind the patient or org index; page size <= 50; never OFFSET and never COUNT(*) over a chart table.
- Caching: Only non-PHI reference data (code sets, provider directory, location list) is cached, in memory with a short TTL; chart reads are never cached across users and personalised responses carry no-store.
- Idempotency: Note signing, order creation, consent capture and record export take an Idempotency-Key with a unique constraint so a retried tablet request cannot double-sign or double-order.
- Rate limits: Per-user limits on chart opens and searches (a user opening hundreds of charts an hour is flagged and throttled), per-IP limits on login and portal, and per-patient limits on record exports.
- Data growth: encounters, clinical_notes and phi_access_log are range partitioned (year, year, month); partitions are detached to read-only storage after the active window and never dropped before the retention period ends.
- Search: Patient search uses blind-index hashes and prefix keys, never a plaintext trigram index over names; free-text note search is restricted to one patient's chart in phase 1.
Performance targets
| What to measure | Target |
|---|---|
| Chart open (summary) | p95 < 300 ms including the access check and phi_access_log write |
| Patient search | p95 < 150 ms via blind index, <= 25 rows returned |
| Appointment booking | p95 < 200 ms with a double-booking conflict returned as 409 not 500 |
| Note sign | p95 < 250 ms, one transaction |
| Record bundle build | p95 < 60 s for a 5-year chart, asynchronous |
What to watch
- Metric phi access total and denied total: by role and action; a spike in denials or in opens per user is the snooping signal.
- Metric break glass open count: sessions opened and unreviewed, by age.
- Metric unacknowledged abnormal results: count and oldest age; must trend to zero.
- Log structured access logs: request id, actor, patient id hashed, action, outcome; never field values, note text or document names.
- Trace chart open trace: one trace from request through access check, query and audit write.
- Slo audit completeness: 100% of PHI reads have a matching phi_access_log row; any gap is an incident.
- Slo result acknowledgement: 99% of abnormal results acknowledged within the configured window.
- Alert audit chain break: hash chain verification failure pages immediately.
Recurring work
- send_appointment_reminders: runs cron every 15 minutes. Guard: bounded batch, one reminder per (appointment, channel, offset) unique, content restricted to time and place.
- escalate_unacknowledged_results: runs cron every 15 minutes. Guard: claim review_items with SKIP LOCKED, escalate to the covering clinician after the window, capped attempts.
- review_break_glass: runs cron hourly. Guard: opens a compliance review item for every unreviewed session older than 24 h; alerts at 72 h.
- verify_access_chain: runs cron nightly. Guard: recompute the hash chain incrementally from the last verified id; a break is a sev-1 alert.
- build_record_bundle: runs queue (jobs) on approved record request. Guard: idempotent per request id, private bucket, 24 h signed URL, writes disclosure row.
- expire_sessions_and_urls: runs cron hourly. Guard: expires break-glass sessions and removes expired export bundles in bounded batches.
Add when the numbers say so
- Read replicas: Compliance reports and access-log analytics run on a read replica once primary CPU > 60% sustained; clinical reads and writes stay on the primary.
- Storage: Documents live in a private bucket with per-object keys, lifecycle to infrequent-access after 90 days, and no public listing; thumbnails are generated on demand, never stored with a public URL.
Deferred until it is needed
| Deferred | Adopt it when |
|---|---|
| FHIR R4 server and HL7 v2 inbound adapter | first lab, pharmacy or HIE integration is contracted. |
| Patient statements and copay payments | practice wants to collect patient balances. |
| Insurance eligibility and claims clearinghouse | practice bills payers. |
| KMS or HSM for data keys | first enterprise customer or security audit. |
| Read replica for compliance analytics | primary CPU > 60% sustained. |
On Forge64
Forge64 matches your description to one of 25 reference architectures, writes the plan and data model into the project, generates the app, and runs a quality gate over the code before you see it. Each app gets its own Postgres database and sign-in with no per-user fee. Hosting on Forge Cloud and Forge Payments are rolling out.
Every metered resource on Forge64 has a hard cap, so a traffic spike stops at your limit instead of becoming a surprise bill. This is a reference design for the category, not a promise that every item is generated today. Built-ins such as background jobs, file uploads and search are rolling out; email sent from your app is coming soon, so anything here that needs it is something you add yourself for now.
FAQ
- When should I worry about scale for a clinic records app?
- Not before a measured trigger fires. For example, for "FHIR R4 server and HL7 v2 inbound adapter": first lab, pharmacy or HIE integration is contracted.
- What performance targets should a clinic records app aim for?
- Chart open (summary): p95 < 300 ms including the access check and phi_access_log write. Patient search: p95 < 150 ms via blind index, <= 25 rows returned. Appointment booking: p95 < 200 ms with a double-booking conflict returned as 409 not 500.
- Does Forge64 cap my usage costs?
- Yes. Every metered resource has a hard cap, and paid plans add an overage spend cap that you set.
Build your app with Forge64
One prompt to a running app with auth, database, hosting and payments. Start free, no credit card required.
Start building for free