Skip to main content

Notification — How it works

Overview

The notification engine manages reusable message templates and the events/deliveries that send them. An event is rendered from a template, dispatched through a pluggable provider, and every attempt is recorded append-only — so provider failures and retries never lose history. Recipient, body, and payload may be PHI and are never logged.

Data model & ownership

TablePurpose
notification_templateReusable template; relational channel (EMAIL/SMS/PUSH/IN_APP/WEBHOOK), code unique per tenant, {{variable}} subject/body + required_variables.
notification_eventAn enqueued message; relational status (PENDING/SENT/FAILED/CANCELLED), rendered subject/body, payload.
notification_deliveryAppend-only per-attempt outcome; relational status (SENT/FAILED), provider + non-sensitive response snapshot.

Key rules & invariants

  • Template validation rejects an EMAIL template without a subject and any declared required variable not referenced in the subject/body; voided templates cannot be used for new deliveries.
  • Enqueue renders the subject/body from the template ({{variable}} substitution) and rejects a missing required variable / invalid payload JSON.
  • Send dispatches via the NotificationProvider SPI (a SimulatedNotificationProvider ships by default) and records a new notification_delivery per attempt; a provider failure is captured as a FAILED attempt (not thrown) and a retry appends another attempt — history is never lost.
  • No PHI/secrets are logged — only ids and statuses.

API

See the API Reference. Endpoint groups under /api/v1/notification: templates, and events (enqueue/get/search) + /{id}/send, /{id}/deliveries.

Configuration & feature flags

Domain-module Feign URL notification.service.url (NOTIFICATION_SERVICE_URL). Real email/SMS/push providers plug in behind the NotificationProvider SPI (follow-up).