DEV Community

Cover image for Building Telehealth That Handles Latency, EHR Integration, and HIPAA Safeguards
Om Jariwala
Om Jariwala

Posted on AI-assisted

Building Telehealth That Handles Latency, EHR Integration, and HIPAA Safeguards

A telehealth app can pass every demo and still fail in production. The video freezes on a patient's rural 4G connection. The EHR sync silently drops a medication update. A debug log captures a diagnosis in plain text.

Healthcare software is judged on a different scale than most products. A glitch isn't just a bad review, it's a clinical risk and a compliance risk. Here are the three problems that cause the most trouble, and how to design for them from day one.

1. Latency: design for the worst network, not the best

A video visit with a 2-second delay isn't a consultation, it's two people talking over each other. Most of your patients won't be on office fiber.

Use WebRTC, but plan for what it doesn't solve.

  • Run TURN servers. Direct peer-to-peer fails behind many corporate and mobile NATs. Without TURN fallback, those users simply can't connect.
  • Use an SFU for anything beyond 1:1. Group visits (patient, doctor, interpreter, family member) don't scale on mesh topologies.
  • Deploy media servers close to users. Region-aware routing often does more for perceived quality than any codec tuning.
  • Degrade gracefully. When bandwidth drops, reduce video resolution first, then fall back to audio-only. Audio is what carries the consultation.

Add a pre-call check so problems surface before the visit starts:

async function preCallCheck() {
  const pc = new RTCPeerConnection({ iceServers });
  pc.createDataChannel("probe");
  await pc.setLocalDescription(await pc.createOffer());

  const stats = await collectIceStats(pc); // RTT, candidate types
  const usingRelay = stats.selectedCandidateType === "relay";

  return {
    rttMs: stats.rtt,
    usingRelay,
    recommendation: stats.rtt > 300 ? "audio-only" : "video",
  };
}
Enter fullscreen mode Exit fullscreen mode

Measure what matters in production: time-to-first-frame, reconnection rate, packet loss, and join-failure rate. Track them per region and per network type, because averages hide the patients who struggle most.

2. EHR integration: assume the other system is slow, strict, and inconsistent

Integrating with EHRs is less about writing API calls and more about surviving their quirks.

Standardize on FHIR where you can. HL7 FHIR R4 with SMART on FHIR (OAuth 2.0) is the most realistic path to interoperability. Expect to still handle HL7 v2 messages and vendor-specific extensions for older systems.

Never block the visit on an EHR call. Treat EHR writes as asynchronous:

# Visit ends -> enqueue, don't call the EHR inline
def on_visit_completed(visit):
    outbox.add(
        type="encounter.create",
        idempotency_key=f"visit-{visit.id}",
        payload=build_fhir_encounter(visit),
    )

# Worker: retries with backoff, safe to run twice
def process_outbox(item):
    try:
        ehr_client.post("/Encounter", item.payload,
                        headers={"If-None-Exist": item.idempotency_key})
        item.mark_done()
    except TransientError:
        item.retry_with_backoff()
    except ValidationError as e:
        item.send_to_dead_letter(e)  # needs human review
Enter fullscreen mode Exit fullscreen mode

The patterns worth adopting:

  • Outbox pattern. Write the clinical record and the sync job in the same database transaction so nothing is lost between them.
  • Idempotency keys. Retries are guaranteed, so duplicate encounters must be impossible.
  • Dead-letter queues with alerting. A failed sync of a prescription or note should page someone, not disappear.
  • Patient matching with care. Matching on name and date of birth alone creates wrong-chart risk. Use the EHR's identifiers (MRN, FHIR Patient IDs) and treat ambiguous matches as a manual review case.
  • Map data explicitly. Keep a versioned mapping layer between your internal model and FHIR resources, so one EHR's quirk doesn't leak into your whole codebase.

3. HIPAA safeguards: compliance is a system property, not a library

No framework makes you "HIPAA compliant" on its own. Compliance combines technical controls, policies, and agreements. On the technical side, the HIPAA Security Rule's safeguards translate into concrete engineering work:

Safeguard What it looks like in practice
Access control Role-based access, unique user IDs, MFA, automatic session timeout
Audit controls Immutable logs of who accessed which record, when, and why
Integrity Checksums, versioned records, protection against silent modification
Transmission security TLS 1.2+ everywhere, DTLS-SRTP for WebRTC media
Encryption at rest Managed keys (KMS), per-environment separation, rotation

A few mistakes show up repeatedly:

  • PHI in logs and error trackers. Scrub request bodies, and never log full payloads from clinical endpoints.
  • PHI in push notifications and emails. "Your lab result for diabetes is ready" leaks information on a lock screen. Keep notifications generic.
  • Recording by default. Store only what you need (the minimum necessary standard), with explicit consent flows.
  • Non-production environments with real data. Use synthetic or de-identified data in dev and staging.
  • Missing Business Associate Agreements. Every vendor that touches PHI (cloud, video, SMS, analytics) needs a BAA, and some tools you rely on may not offer one.

A simple audit log middleware is a good start:

app.use("/api/patients/:id", async (req, res, next) => {
  res.on("finish", () => {
    auditLog.write({
      actor: req.user.id,
      role: req.user.role,
      action: `${req.method} ${req.route.path}`,
      patientId: req.params.id,
      outcome: res.statusCode,
      ip: req.ip,
      at: new Date().toISOString(),
    });
  });
  next();
});
Enter fullscreen mode Exit fullscreen mode

Putting it together

These three concerns pull against each other. Encryption and audit logging add overhead, EHR sync adds failure modes, and real-time video leaves no room for either. Teams that handle this well do a few things consistently:

  1. Decouple real-time from record-keeping. The video path stays fast, and clinical documentation flows through reliable async pipelines.
  2. Build observability in early. You can't fix latency or sync failures you can't see.
  3. Treat compliance as part of the architecture review, not a checklist before launch.

Patients never see any of this. They only notice whether the call connected, whether their doctor had their history, and whether they felt safe. That's what trust in telehealth is built on.

What's the hardest part of telehealth engineering you've run into: media quality, EHR quirks, or compliance? Share it in the comments.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.