Skip to main content
Version: 1.0 Last Updated: 2026-03-15 Status: Architecture Reference Related: PF_FW_BUSINESS_AUTOMATION_WORKFLOW_ARCHITECTURE_RESEARCH.md Recommendation: R-FW-12

Overview

Encore OS uses 5 distinct event delivery paths to handle the full spectrum of reactive behavior across the platform — from real-time UI updates to durable business automation to external system integration. Each path makes different trade-offs around durability, latency, retry semantics, and auditability. Choosing the wrong path leads to subtle bugs: lost events, duplicate processing, blocked request cycles, or audit gaps that surface during compliance reviews. This document gives developers a clear framework for selecting the right delivery path for any given use case. Key principle: prefer the least powerful path that satisfies your requirements. UI updates do not need durable queues. Business workflows should not depend on WebSocket connectivity. External integrations must not block database triggers.

Event Delivery Paths

Path 1: Table-Driven Domain Events (Primary)

Role: The backbone of Encore OS business automation. Domain events are the canonical mechanism for triggering workflows, automation rules, and cross-core reactions. Flow:
Use when:
  • Business automation triggers (e.g., “when a resident moves in, create billing record”)
  • Workflow execution that must survive server restarts
  • Cross-core reactions that need an audit trail
  • Any event that compliance or governance may need to review
Guarantees: Key tables: Latency: 10-30 seconds (pg_cron poll interval). Not suitable for user-facing real-time feedback. Example event types:
  • resident.moved_in, resident.moved_out, resident.status_changed
  • invoice.created, payment.received, claim.submitted
  • staff.onboarded, credential.expiring, shift.completed

Path 2: HTTP Event Consumer (Synchronous)

Role: Immediate, request-scoped side effects that must complete before responding to the user. Flow:
Use when:
  • Immediate side effects needed in the request cycle (e.g., send welcome email on signup)
  • Real-time validation against external systems
  • Operations where the caller needs confirmation of completion
  • Simple request-response patterns that do not fan out
Guarantees: Latency: < 2 seconds for typical operations. When NOT to use:
  • Long-running workflows (> 10 seconds)
  • Fan-out to multiple consumers
  • Operations that must retry on failure without user intervention

Path 3: Supabase Realtime (UI Updates Only)

Role: Push updates to connected browser clients for live UI reactivity. This path is strictly for display purposes and must never drive business logic. Flow (Postgres Changes):
Flow (Broadcast):
Use when:
  • Notification badge counts and live notification feeds
  • Dashboard widgets that reflect latest data
  • Presence indicators (who is online, who is editing)
  • Collaborative editing cursors or selection highlights
  • Live list/table updates without polling
Guarantees: Latency: < 500 milliseconds (WebSocket push). NOT suitable for:
  • Business logic execution
  • Data consistency enforcement
  • Audit-required operations
  • Anything that must happen even if no client is connected

Path 4: External Event Forwarding (PF-35 Phase 2)

Role: Deliver events to external systems (EHR platforms, clearinghouses, payer portals, partner organizations) via outbound webhooks with compliance safeguards. Flow:
Use when:
  • External EHR system integration (HL7 FHIR event notifications)
  • Clearinghouse claim status callbacks
  • Payer portal authorization updates
  • Partner organization data sharing
  • Webhook-based integrations with third-party platforms
Guarantees: Key tables: Compliance:
  • 42 CFR Part 2: Before forwarding any event involving substance abuse treatment data, the consent guard verifies that appropriate patient consent exists for the receiving organization. Events without valid consent are blocked and logged.
  • HIPAA: Payload transformation strips internal identifiers and limits PHI to the minimum necessary for the subscriber’s stated purpose.
  • Audit: Every forwarding attempt (success or failure) is logged with timestamp, subscriber ID, response status, and payload hash.
Supports:
  • Glob pattern matching on event types (e.g., resident.*, billing.payment.*)
  • JSONPath payload transformation for per-subscriber field selection
  • Per-subscriber retry configuration
  • Webhook signature verification (HMAC-SHA256)
Latency: 30 seconds to 5 minutes depending on queue depth and retry schedule.

Path 5: pgmq Direct Queue (Internal Async)

Role: General-purpose internal async processing with guaranteed delivery and backpressure support. Used when work must happen asynchronously but does not fit the domain event / workflow model. Flow:
Active queues in Encore OS: Use when:
  • Guaranteed async processing with backpressure
  • Batch operations (e.g., nightly report generation, bulk imports)
  • Rate-limited external API calls (e.g., clearinghouse submissions)
  • Work that benefits from visibility timeout to prevent double-processing
  • Fan-out from a single event to multiple independent work items
Guarantees: Latency: Depends on consumer poll interval. Typically 5-60 seconds.

Decision Tree

Use this flowchart to select the appropriate event delivery path:

Path Comparison Matrix


Composed Patterns

Many real-world scenarios combine multiple paths. Here are common compositions:

Resident Move-In (Paths 1 + 3 + 5)

Claim Submission (Paths 1 + 4 + 2)


Anti-Patterns

1. Using Realtime (Path 3) for Business Logic

Wrong:
Why it fails: Realtime is best-effort. If the browser tab closes, the billing record is never created. There is no retry, no audit trail, and no guarantee of delivery. Correct: Use Path 1 (domain events) to trigger the billing workflow server-side.

2. Using HTTP Consumer (Path 2) for Long-Running Workflows

Wrong:
Why it fails: Edge Functions have execution time limits. Long workflows should be broken into steps and processed asynchronously. Correct: Use Path 1 (domain events) to enqueue the workflow, which the worker processes step-by-step with checkpointing.

3. Bypassing Domain Events for Automatable Triggers

Wrong:
Why it fails: No audit trail, no pattern matching, no ability to configure or disable the automation via the UI, no visibility into what triggered what. Correct: Publish a domain event and let the automation engine match it to configured rules.

4. Calling External APIs Synchronously from DB Triggers

Wrong:
Why it fails: Database triggers run inside the transaction. If the external API is slow or down, the transaction is blocked or rolled back, affecting the user. Correct: Use Path 4 (external event forwarding) to asynchronously deliver the event to the EHR with retry and DLQ support.

5. Using pgmq for User-Facing Real-Time Feedback

Wrong:
Why it fails: Polling adds unnecessary load and latency. The browser should not interact with pgmq directly. Correct: Use Path 5 (pgmq) for the async processing, then use Path 3 (Realtime) to push the result to the UI when processing completes.

Failure Handling Summary


Monitoring and Observability

Each path has different monitoring needs:

Multi-Tenancy Considerations

All event delivery paths enforce tenant isolation:
  • Path 1: fw_domain_events.organization_id scopes events; RLS policies prevent cross-tenant reads; trigger matching is org-scoped.
  • Path 2: Edge Function receives organization_id from authenticated JWT; all queries are tenant-filtered.
  • Path 3: Realtime channels include org ID in channel name (e.g., org:{uuid}:notifications); RLS on underlying tables.
  • Path 4: pf_event_subscriptions.organization_id ensures subscribers only receive their own events; consent checks are per-org.
  • Path 5: pgmq messages include organization_id in payload; consumers filter and validate.


Revision History