medOS ultra

Edge Functions Architecture

Serverless compute layer on Supabase Edge Functions (Deno) - orchestrators, matchers, dispatchers.

7 min read diagramsUpdated 2026-03-26docs/architecture/architecture/01-edge-functions.md

Serverless compute layer — Supabase Edge Functions (Deno Deploy)


Overview

MedOS uses Supabase Edge Functions as its serverless compute layer — no AWS Lambda, SAM, or CDK. All functions run on Deno Deploy with TypeScript, invoked via HTTP POST or Postgres database triggers.

Two deployment targets exist:

Deployment Location Functions
Clinic Frontend ever-medos-global-pure-react/supabase/functions/ 5 functions
Medbase HIS Backend his-vajira/medbase/supabase/functions/ 1 function (+ 15 planned)

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────┐
│                        INGRESS LAYER                                │
├─────────────┬──────────────┬──────────────┬─────────────────────────┤
│  React UI   │  Metriport   │  Postgres    │  WebhookDispatcher      │
│  (HTTP POST)│  (Webhook)   │  (DB Trigger)│  (HMAC-signed POST)     │
└──────┬──────┴──────┬───────┴──────┬───────┴──────────┬──────────────┘
       │             │              │                   │
       ▼             ▼              ▼                   ▼
┌──────────────────────────────────────────────────────────────────────┐
│                   SUPABASE EDGE FUNCTIONS (Deno)                     │
│                                                                      │
│  ┌──────────────────┐  ┌──────────────────┐  ┌───────────────────┐  │
│  │   claim-coder    │  │ diagnosis-assist  │  │ patient-screener  │  │
│  │   ──────────     │  │ ───────────────   │  │ ────────────────  │  │
│  │  Medical Record  │  │  Symptoms+History │  │  Intake Data      │  │
│  │       ↓          │  │       ↓           │  │       ↓           │  │
│  │  Dify AI (POST)  │  │  Dify AI (POST)   │  │  Dify AI (POST)  │  │
│  │       ↓          │  │       ↓           │  │       ↓           │  │
│  │  ICD/CPT Codes   │  │  Diff. Diagnoses  │  │  Risk Score       │  │
│  └────────┬─────────┘  └────────┬──────────┘  └────────┬──────────┘  │
│           │                     │                       │            │
│  ┌────────▼─────────────────────▼───────────────────────▼──────────┐ │
│  │                    _shared/difyClient.ts                         │ │
│  │  callDifyClaimCoder() | callDifyDiagnosisAssistant()            │ │
│  │  callDifyPatientScreener() | callDifyWorkflow()                 │ │
│  └─────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  ┌──────────────────┐  ┌──────────────────────────────────────────┐  │
│  │  fhir-webhook    │  │  integration-health-check                │  │
│  │  ──────────────  │  │  ────────────────────────                │  │
│  │  Metriport POST  │  │  connection_id → fetch(base_url)        │  │
│  │  HMAC verify     │  │  Latency measurement                    │  │
│  │  Event dispatch: │  │  Status: ok/error + latency_ms          │  │
│  │  • doc-download  │  │                                          │  │
│  │  • doc-convert   │  └──────────────────────────────────────────┘  │
│  │  • consolidated  │                                                │
│  └──────────────────┘                                                │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────────┐│
│  │              encounter-orchestrator (~30k LOC)                    ││
│  │  ─────────────────────────────────────────────                   ││
│  │  Ingress: DB Trigger | WebhookDispatcher | Direct POST           ││
│  │                                                                   ││
│  │  Events:                                                          ││
│  │  encounter.opened/progressed/closed                               ││
│  │  order.placed/fulfilled/cancelled                                 ││
│  │  lab.resulted | imaging.resulted | medication.administered        ││
│  │  alert.issued/resolved                                            ││
│  │                                                                   ││
│  │  Outputs → encounter_journey_cache (read model)                   ││
│  │          → department_queues (operational queues)                  ││
│  │          → dlq (dead letter queue on error)                       ││
│  │                                                                   ││
│  │  Features: dedup by event_id | dept routing | alert pruning       ││
│  │            DLQ for retry | latency logging                        ││
│  └──────────────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────────────┘
       │             │              │                   │
       ▼             ▼              ▼                   ▼
┌──────────────────────────────────────────────────────────────────────┐
│                      PERSISTENCE LAYER                               │
│                                                                      │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────┐  │
│  │ Supabase Postgres│  │ Dify AI Platform │  │ External Systems    │  │
│  │ ───────────────  │  │ ──────────────── │  │ ─────────────────   │  │
│  │ claim_coding_req │  │ Workflow Engine   │  │ Metriport (HIN)    │  │
│  │ diagnosis_req    │  │ (hosted/self)     │  │ EHR endpoints      │  │
│  │ screening_req    │  │                   │  │ Integration URLs    │  │
│  │ fhir_hin_docs    │  └─────────────────┘  └─────────────────────┘  │
│  │ fhir_audit_log   │                                                │
│  │ encounter_cache  │                                                │
│  │ department_queues│                                                │
│  │ integration_conn │                                                │
│  └─────────────────┘                                                 │
└──────────────────────────────────────────────────────────────────────┘

Function Details

1. claim-coder

Property Value
Path ever-medos-global-pure-react/supabase/functions/claim-coder/index.ts
Trigger HTTP POST from React frontend
Auth Supabase JWT (from request header)
AI Backend Dify workflow via DIFY_CLAIM_CODER_ENDPOINT
Input { claimCodingData: { medicalRecord: string } }
Output { suggested_icd_codes, suggested_cpt_codes }
DB Table claim_coding_requests (request + response + user_id)

2. diagnosis-assistant

Property Value
Path ever-medos-global-pure-react/supabase/functions/diagnosis-assistant/index.ts
Trigger HTTP POST from React frontend
Auth Supabase JWT
AI Backend Dify workflow via DIFY_DIAGNOSIS_ASSISTANT_ENDPOINT
Input { patientData: { symptoms, historyAndContext, keyTestResults, vitals? } }
Output { potential_diagnoses, suggested_orders: { labs, imaging, meds, consults } }
DB Table diagnosis_assistant_requests

3. patient-screener

Property Value
Path ever-medos-global-pure-react/supabase/functions/patient-screener/index.ts
Trigger HTTP POST from React frontend
Auth Supabase JWT
AI Backend Dify workflow via DIFY_PATIENT_SCREENER_ENDPOINT
Input { intakeData: { age, presentingComplaint, medicalHistory, medications, allergies } }
Output { identified_risks, suggested_actions, risk_score }
DB Table patient_screening_requests

4. fhir-webhook

Property Value
Path ever-medos-global-pure-react/supabase/functions/fhir-webhook/index.ts
Trigger Metriport webhook POST (external HIN provider)
Auth HMAC-SHA256 signature via x-metriport-signature header
Events medical.document-download, medical.document-conversion, medical.consolidated-data
DB Tables fhir_hin_documents, fhir_hin_patient_map, fhir_audit_log
Features Dedup by metriport_doc_id, status tracking (downloaded → converted)

5. integration-health-check

Property Value
Path ever-medos-global-pure-react/supabase/functions/integration-health-check/index.ts
Trigger HTTP POST from frontend or scheduled checks
Input { connection_id: string }
Output { status, latency_ms, http_status, error? }
DB Table integration_connections (updates last_health_check, health_check_ok)
Timeout 10 seconds per check

6. encounter-orchestrator

Property Value
Path his-vajira/medbase/supabase/functions/encounter-orchestrator/index.ts
Scale ~30,500 LOC — the largest edge function
Triggers 3 ingress paths (DB trigger, WebhookDispatcher, Direct POST)
Auth HMAC-SHA256 (x-vajira-signature) or Service Role Key
Events 11 event types (encounter, order, lab, imaging, medication, alert)
Output Tables encounter_journey_cache, department_queues, dlq
Features Event dedup, department routing, alert pruning (max 50), DLQ, latency logging

Environment Variables

# Clinic Frontend Functions
DIFY_API_KEY=                          # Dify platform auth
DIFY_CLAIM_CODER_ENDPOINT=            # Claim coding workflow URL
DIFY_DIAGNOSIS_ASSISTANT_ENDPOINT=    # Diagnosis workflow URL
DIFY_PATIENT_SCREENER_ENDPOINT=       # Screening workflow URL
SUPABASE_URL=                          # Supabase project URL
SUPABASE_ANON_KEY=                     # Supabase public key
METRIPORT_WEBHOOK_SECRET=             # FHIR webhook HMAC secret

# Medbase Backend Function
SUPABASE_SERVICE_ROLE_KEY=            # Privileged DB access
VAJIRA_WEBHOOK_SECRET=                # Internal webhook HMAC secret
WEBHOOK_SECRET=                        # Alternate webhook secret

Shared Utilities

_shared/difyClient.ts (Clinic)

Centralized Dify AI workflow client with endpoint routing and auth injection. All three AI functions delegate to this shared module.

_shared/medbase-client.ts (Medbase)

MongoDB admin client for encounter-orchestrator’s read model projections.

_shared/event-contract.ts (Medbase)

Event type normalization — maps raw webhook payloads to typed HospitalEvent union.

_shared/hmac.ts (Medbase)

HMAC-SHA256 signature verification for webhook security.


Data Flow Patterns

AI Clinical Decision Support (claim-coder, diagnosis-assistant, patient-screener)

React UI → POST + JWT → Edge Function → Validate Auth → Call Dify AI → Store to DB → Return Response

FHIR Health Information Network (fhir-webhook)

Metriport → POST + HMAC → Edge Function → Verify Signature → Parse Event → Upsert Documents → Audit Log

Encounter Event Projection (encounter-orchestrator)

Backend API Write → Postgres Trigger OR WebhookDispatcher → Edge Function → Dedup Check
  → Project to encounter_journey_cache + department_queues → Supabase Realtime → React UI
  → On Error: Write to DLQ

Deployment

# Deploy individual function
supabase functions deploy claim-coder
supabase functions deploy encounter-orchestrator

# Set secrets
supabase secrets set DIFY_API_KEY=xxx METRIPORT_WEBHOOK_SECRET=yyy

Key Design Decisions

  1. Supabase over AWS Lambda — Tight integration with Supabase Postgres, Realtime channels, and Auth. No cold start issues with Deno Deploy.
  2. Dify as AI orchestrator — Externalizes prompt engineering and workflow management to Dify platform rather than embedding in edge functions.
  3. encounter-orchestrator as CQRS projection — Implements the “write model” → “read model” pattern. Backend writes to hospital_events, the orchestrator projects to query-optimized caches.
  4. HMAC for webhook security — Both external (Metriport) and internal (WebhookDispatcher) webhooks are HMAC-verified.
  5. DLQ pattern — Failed events go to dead letter queue for retry/audit rather than being lost.
Ask Anything